考虑每一个数对于答案的贡献。复杂度是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
",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