[SDOI2008]仪仗队
题目描述
作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。 现在,C君希望你告诉他队伍整齐时能看到的学生人数。
输入输出格式
输入格式:
共一个数N
输出格式:
共一个数,即C君应看到的学生人数。
输入输出样例
输入样例#1:
4
输出样例#1:
9
说明
【数据规模和约定】
对于 100% 的数据,1 ≤ N ≤ 40000
又是一道欧拉函数的题
本身不难。就是求多少种不同的斜率,也就是小于n互质数,直接套用欧拉函数
线性筛法。
但此题n要先减1,原因:
左下角为(0,0),之所以要这样,是避免斜率为0的直线被作为1/1,1/2,1/3....计算多次
把n-1后对1~n进行处理,得到ans=sum(phi[1~n])
因为x,y可以互换,ans*=2;因为斜率1直线算了两次,所以ans--;
还有两条直线,ans+=2;输出
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 long long phi[40005],ans; 8 bool mark[40005]; 9 int n,tot,prime[40005]; 10 int main() 11 {long long i; 12 long long j; 13 cin>>n; 14 n--; 15 phi[1]=1; 16 for (i=2;i<=n;i++) 17 { 18 if (mark[i]==0) 19 { 20 prime[++tot]=i; 21 phi[i]=i-1; 22 } 23 for (j=1;j<=tot;j++) 24 { 25 long long k=i*prime[j]; 26 if (k>n) break; 27 mark[k]=1; 28 if (i%prime[j]==0) 29 { 30 phi[k]=phi[i]*prime[j]; 31 break; 32 } 33 else phi[k]=phi[i]*(prime[j]-1); 34 } 35 phi[i]+=phi[i-1]; 36 //cout<<i<<' '<<phi[i]<<endl; 37 } 38 cout<<phi[n]*2+1; 39 }