【bzoj 2190】[SDOI2008]仪仗队(线性筛)
2190: [SDOI2008]仪仗队
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 2659 Solved: 1690
[Submit][Status][Discuss]
Description
作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。 现在,C君希望你告诉他队伍整齐时能看到的学生人数。
Input
共一个数N。
Output
共一个数,即C君应看到的学生人数。
Sample Input
4
Sample Output
9
HINT
【数据规模和约定】 对于 100% 的数据,1 ≤ N ≤ 40000
Source
【题解】【线性筛】
【能被看见的条件是gcd(x,y)=1,按对角线分开,容易发现i行能被看到的人数是phi(i),线性筛ph, 求和,*2,+1】
【线性筛的基本应用,以对角线为轴,劈成两半,只计算一半,然后×2,再加上对角线上的一个,注意计算时,因为1与任何数都不互质,所以要少算一列,加phi时也要少加一列,就可以了】
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
long long n,prime[40010],phi[40010],ans;
bool p[40010];
int main()
{
int i,j;
scanf("%lld",&n);
phi[1]=1; p[1]=1;
for (i=2;i<=n-1;++i)
{
if (!p[i])
{
prime[++prime[0]]=i;
phi[i]=i-1;
}//判断是否是素数
for (j=1;j<=prime[0];++j)
{
if (i*prime[j]>n) break;
p[i*prime[j]]=1;
if (i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
for (i=1;i<=n-1;i++)
ans+=phi[i];
ans*=2;++ans;
printf("%lld",ans);
return 0;
}
既然无能更改,又何必枉自寻烦忧