BZOJ#4804. 欧拉心算
4804: 欧拉心算
Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 508 Solved: 298
[Submit][Status][Discuss]
Description
给出一个数字N
Input
第一行为一个正整数T,表示数据组数。
接下来T行为询问,每行包含一个正整数N。
T<=5000,N<=10^7
Output
按读入顺序输出答案。
Sample Input
1
10
10
Sample Output
136
problem:
solution:
枚举gcd:
套路求gcd==1:
根据公式二可得:
枚举di:
现在就要预处理出:
发现φ和μ都是积性函数,所有h也是积性函数,但不是完全积性,所有在线性筛时我们要分类讨论:
if(i*prime[j]>N) break; vis[i*prime[j]]=1; if(i%prime[j]==0) { if(i/prime[j]%prime[j]==0) h[i*prime[j]]=h[i]*prime[j];//a,b不互质 else h[i*prime[j]]=h[i/prime[j]]*(long long)(prime[j]-1)*(prime[j]-1);//根据积性函数性质 break; } h[i*prime[j]]=h[i]*h[prime[j]];
附上代码:
#include<bits/stdc++.h> using namespace std; const int N=1e7+12; int prime[N],cnt,vis[N]; long long h[N],ans; void getmu() { h[1]=1; for(int i=2;i<=N;i++) { if(!vis[i]) prime[++cnt]=i,h[i]=i-2; for(int j=1;j<=cnt;j++) { if(i*prime[j]>N) break; vis[i*prime[j]]=1; if(i%prime[j]==0) { if(i/prime[j]%prime[j]==0) h[i*prime[j]]=h[i]*prime[j]; else h[i*prime[j]]=h[i/prime[j]]*(long long)(prime[j]-1)*(prime[j]-1); break; } h[i*prime[j]]=h[i]*h[prime[j]]; } } for(int i=2;i<=N;i++) h[i]=h[i-1]+h[i]; } int main() { // freopen("a.in","r",stdin); getmu(); int T;scanf("%d",&T); while(T--) { int n; scanf("%d",&n); int pos; ans=0; for(int i=1;i<=n;i=pos+1) { pos=n/(n/i); ans+=(long long)(n/i)*(n/i)*(h[pos]-h[i-1]);//注意long long } printf("%lld\n",ans); } return 0; }