P2568 GCD
https://www.luogu.org/problemnew/show/P2568
思路:
1.题目要求
考虑枚举的情况,问题转换为
即
然后就能用mobius做了。(别忘了开long long
AC Code:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N=1e7+10; int pri[N],vis[N],mu[N]; void euler(int n){ mu[1]=1; for(int i=2;i<=n;i++){ if(!vis[i]) vis[i]=i,pri[++pri[0]]=i,mu[i]=-1; for(int j=1;j<=pri[0];j++){ if(vis[i]<pri[j]||i*pri[j]>n) break; vis[i*pri[j]]=pri[j]; mu[i*pri[j]]=mu[i]*(i%pri[j]?-1:0); if(i%pri[j]==0) break; } } for(int i=1;i<=n;i++) mu[i]+=mu[i-1]; } ll cal(int n){ ll ans=0; for(int d=1;d<=pri[0];d++){ int lim=n/pri[d]; for(int l=1,r;l<=lim;l=r+1){ r=(lim/(lim/l)); ans+=(long long)(mu[r]-mu[l-1])*(lim/l)*(lim/l); //开longlong啊!! } } return ans; } int main(){ int n;scanf("%d",&n); euler(n); ll ans=cal(n); printf("%lld",ans); return 0; }
2.本题还可以用欧拉函数做:
对于这个式子:
表示以内互质的数的对数,即为,其中代表的前缀和。由于答案要求数对有序,所以ans=,其中减去的是多加一次的。
注意:1.long long 类型的数组不要开太多。