【BZOJ】2190 [SDOI2008]仪仗队
【算法】欧拉函数 欧拉线性筛
【题解】将图从左至右,从下至上,分别标号0~n-1。
除了坐标0,一个点会被观察到当且仅当其坐标(i,j)的i与j互质,否则会被(i/d,j/d)挡住。
所以累加2~n-1的欧拉函数,再在处理左下角三个点即可。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=40010; int n,phi[maxn],prime[maxn]; bool mark[maxn]; void pre_phi(int x) { phi[1]=1;int tot=0; memset(mark,0,sizeof(mark)); for(int i=2;i<=x;i++) { if(!mark[i]) { prime[++tot]=i; phi[i]=i-1; } for(int j=1;j<=tot;j++) { if(i*prime[j]>x)break; mark[i*prime[j]]=1;//筛 if(i%prime[j]==0)phi[i*prime[j]]=phi[i]*prime[j]; else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } // for(int i=1;i<=x;i++)printf("phi[%d]=%d\n",i,phi[i]); } int main() { scanf("%d",&n); pre_phi(n-1); int ans=1; for(int i=2;i<=n-1;i++)ans+=phi[i]; printf("%d",ans*2+1); return 0; }