复习一波反演。
非常粗暴的就是F(1)+2。
注意范围应该是n-1,因为在坐标系上,只有在原点看,点(1,2)才会挡住(2,4),最后加2就是上面和右边的两个点。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int pr,prime[41000],u[41000]; bool v[41000]; void mobius_inversion() { pr=0;u[1]=1; memset(v,true,sizeof(v)); for(int i=2;i<=40000;i++) { if(v[i]==true) { prime[++pr]=i; u[i]=-1; } for(int j=1;j<=pr&&i*prime[j]<=40000;j++) { v[i*prime[j]]=false; if(i%prime[j]==0){u[i*prime[j]]=0;break;} u[i*prime[j]]=-u[i]; } u[i]+=u[i-1]; } } int getF(int n) { int F=0,last; for(int d=1;d<=n;d=last+1) { last=n/(n/d); int G=(n/d)*(n/d); F+=(u[last]-u[d-1])*G; } return F; } int main() { mobius_inversion(); int n; scanf("%d",&n); printf("%d\n",getF(n-1)+2); return 0; }