BZOJ2190 [SDOI2008]仪仗队(欧拉函数)
与HDU2841大同小异。
设左下角的点为(1,1),如果(1,1)->(x,y)和(1,1)->(x',y')向量平行,那只有在前面的能被看见。然后就是求x-1、y-1不互质的数对个数。
而x或y等于1可以另外讨论一下,就是当n不等于1时就有两个,n等于1就特判一下。
那么就用欧拉函数计数了:枚举x-1,累加小于x-1与x-1互质的个数,即合法的y-1的个数;结果还要*2,因为还有一半对称的y-1>x-1的情况;此外x-1=y-1多算了一次,减去1即可。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 #define MAXN 43210 5 int phi[MAXN],prime[MAXN]; 6 bool vis[MAXN]; 7 void euler(){ 8 phi[1]=1; 9 int tot=0; 10 for(int i=2; i<MAXN; ++i){ 11 if(!vis[i]){ 12 prime[tot++]=i; 13 phi[i]=i-1; 14 } 15 for(int j=0; j<tot; ++j){ 16 if(i*prime[j]>MAXN) break; 17 vis[i*prime[j]]=1; 18 if(i%prime[j]==0){ 19 phi[i*prime[j]]=phi[i]*prime[j]; 20 break; 21 }else{ 22 phi[i*prime[j]]=phi[i]*(prime[j]-1); 23 } 24 } 25 } 26 } 27 int main(){ 28 euler(); 29 int n; 30 scanf("%d",&n); 31 if(n==1){ 32 putchar('0'); 33 return 0; 34 } 35 int res=2; 36 for(int i=2; i<=n; ++i){ 37 res+=phi[i-1]<<1; 38 } 39 printf("%d",res-1); 40 return 0; 41 }