仅包含一行,为两个整数n和m。
仅包含一个整数,表示总共产生的能量损失。
欧拉函数:
n m n m min(n,m)
证明过程: ∑ ∑ gcd(i,j)=∑ ∑ ∑ Ø(d) = ∑ Ø(d) * (n/d) *(m/d)
i=1 j=1 i=1 j=1 d|gcd(i,j) d=1
分块写,复杂度 预处理O(1e5)+sqrt(min(n,m));
#include<bits/stdc++.h> using namespace std; #define ll long long #define pi (4*atan(1.0)) const int N=1e5+10,M=1e6+10,inf=1e9+10; const ll INF=1e18+10; ll p[N],ji; bool vis[N]; ll phi[N]; ll sum[N]; void get_eular(int n) { ji = 0; phi[1]=1; memset(vis, true, sizeof(vis)); for(int i = 2; i <= n; i++) { if(vis[i]) { p[ji ++] = i; phi[i] = i - 1; } for(int j = 0; j < ji && i * p[j] <= n; j++) { vis[i * p[j]] = false; if(i % p[j] == 0) { phi[i * p[j]] = phi[i] * p[j]; break; } else phi[i * p[j]] = phi[i] * phi[p[j]]; } } } int main() { get_eular(N); memset(sum,0,sizeof(sum)); for(int i=1;i<=1e5;i++) sum[i]=sum[i-1]+phi[i]; ll x,y; while(~scanf("%lld%lld",&x,&y)) { if(x>y)swap(x,y); ll ans=0; for(int L=1,R=0;L<=x;L=R+1) { R=min(x/(x/L),y/(y/L)); ans+=(sum[R]-sum[L-1])*(x/L)*(y/L); } printf("%lld\n",2*ans-x*y); } return 0; }莫比乌斯:模版题;
gcd(i,j)==k,枚举k;
复杂度O(min(n,m)sqrt(n));
#include<bits/stdc++.h> using namespace std; #define ll long long #define esp 0.00000000001 #define pi 4*atan(1) const int N=1e5+10,M=1e7+10,inf=1e9+10,mod=1e9+7; ll mu[N], p[N], np[N], cnt, sum[N]; void init() { mu[1]=1; for(int i=2; i<N; ++i) { if(!np[i]) p[++cnt]=i, mu[i]=-1; for(int j=1; j<=cnt && i*p[j]<N; ++j) { int t=i*p[j]; np[t]=1; if(i%p[j]==0) { mu[t]=0; break; } mu[t]=-mu[i]; } } for(int i=1;i<N;i++) sum[i]=sum[i-1]+mu[i]; } ll getans(int b,int d) { ll ans=0; for(int L=1,R=0;L<=b;L=R+1) { R=min(b/(b/L),d/(d/L)); ans+=(ll)(sum[R]-sum[L-1])*(b/L)*(d/L); } return ans; } int main() { init(); int b,d,k; while(~scanf("%d%d",&b,&d)) { if(b>d)swap(b,d); ll ans=0; for(int i=1;i<=b;i++) ans+=getans(b/i,d/i)*i; printf("%lld\n",2*ans-(ll)b*d); } return 0; }
转载于:https://www.cnblogs.com/jhz033/p/5817545.html