[luogu P2586] GCD 解题报告 (莫比乌斯反演|欧拉函数)
题目链接:https://www.luogu.org/problemnew/show/P2568#sub
题目大意:
解法一:莫比乌斯反演套路题
其实这样就可以了,但是还可以优化一下子
设T=dp
整除分块就好了,其实这就和 yy的gcd 一样了
解法二:欧拉函数
考虑上面的第一个式子可以化简成
tot是n以内质数的数量
这是因为考虑到每次都两次计算了$\varphi(1)$
#include<algorithm> #include<cstring> #include<cstdio> #include<iostream> using namespace std; typedef long long ll; const int N=1e7+15; int n,tot; ll ans; int prime[5000000]; ll phi[N]; bool vis[N]; void get_phi() { phi[1]=1; for (int i=2;i<=n;i++) { if (!vis[i]) {phi[i]=i-1;prime[++tot]=i;} for (int j=1;j<=tot&&i*prime[j]<=n;j++) { vis[i*prime[j]]=1; if (i%prime[j]) phi[i*prime[j]]=phi[i]*(prime[j]-1); else { phi[i*prime[j]]=phi[i]*prime[j]; break; } } } for (int i=2;i<=n;i++) phi[i]=phi[i-1]+phi[i]; } int main() { scanf("%d",&n); get_phi(); //for (int i=1;i<=n;i++) printf("%d ",phi[i]); for (int i=1;i<=tot;i++) { ans+=phi[n/prime[i]]; } printf("%lld\n",ans*2-tot); return 0; }
星星之火,终将成燎原之势