[SDOI2008]仪仗队
这道题很重要的是分析。
我们从(0,0)开始标号,最后格子为(n-1,n-1)。
一个点(x,y)如果看不到,说明x,y互质。
因为两半具有对称性,所以我们只用算一半。
求与x互质的个数,即是phi(x),预处理phi即可。
除了(1,1)(1,0)(0,1),其余用phi累加即可。
注意:1的特判,线性筛时N开大一点或者写<N而不是<=N。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define LL long long #define re register #define N 40020//开大一点 using namespace std; int read() { int x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } void print(int x) { if(x<0)x=-x,putchar('-'); if(x>9)print(x/10); putchar(x%10+'0'); } int phi[N],prime[N],notp[N]; int tot=0; void init() { for(int i=2;i<=N;++i) { if(!notp[i])prime[++tot]=i,phi[i]=i-1; for(int j=1;j<=tot&&i*prime[j]<=N;++j) { notp[prime[j]*i]=1; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } } int main() { init(); int n=read(); LL ans=0; for(int i=2;i<n;++i)ans+=phi[i]; ans=ans*2; ans+=3; if(n==1)ans=0; printf("%lld\n",ans); }