51nod1188 最大公约数之和 V2
考虑每一个数对于答案的贡献。复杂度是O(nlogn)的。因为1/1+1/2+1/3+1/4......是logn级别的
//gcd(i,j)=2=>gcd(i/2,j/2)=1=>phi(n/d)*d;O(nlogn); #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=5e6+5; int pe[nmax>>3],phi[nmax],q[nmax];bool vis[nmax];ll ans[nmax]; void init(int t){ phi[1]=1;int cnt=0,x; rep(i,2,t){ if(!vis[i]) pe[++cnt]=i,phi[i]=i-1; rep(j,1,cnt){ x=pe[j];if(i*x>t) break;vis[i*x]=1; if(i%x==0) { phi[i*x]=phi[i]*x;break; }else phi[i*x]=phi[i]*phi[x]; } } rep(i,1,t) rep(j,2,t/i) ans[i*j]+=i*phi[j];//gcd(n,n)! rep(i,1,t) ans[i]+=ans[i-1]; } int main(){ int n=read(),mx=0; rep(i,1,n) q[i]=read(),mx=max(mx,q[i]); init(mx); rep(i,1,n) printf("%lld\n",ans[q[i]]); return 0; }
收藏
关注
给出一个数N,输出小于等于N的所有数,两两之间的最大公约数之和。
相当于计算这段程序(程序中的gcd(i,j)表示i与j的最大公约数):
G=0;
for(i=1;i<N;i++)
for(j=i+1;j<=N;j++)
{
G+=gcd(i,j);
}
Input
第1行:1个数T,表示后面用作输入测试的数的数量。(1 <= T <= 50000) 第2 - T + 1行:每行一个数N。(2 <= N <= 5000000)
Output
共T行,输出最大公约数之和。
Input示例
3 10 100 200000
Output示例
67 13015 143295493160