题目描述 Description
作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。
现在,C君希望你告诉他队伍整齐时能看到的学生人数。
输入描述 Input Description
共一个数N。
输出描述 Output Description
共一个数,即C君应看到的学生人数。
样例输入 Sample Input
4
样例输出 Sample Output
9
数据范围及提示 Data Size & Hint
对于 30% 的数据,1≤N≤1000
对于 100% 的数据,1≤N≤40000
题解
记左下角为(0,0),若(x,y)可看见,则gcd(x,y)=1,解析几何或二维向量什么的想一想就能想明白
按y=x把坐标系分成两半。对每一半,第x列上总有phi(x)个可以被看见的;(同理,第y行也总有phi(y)个可以被看见的。这两个里用一个就可以的)(phi为欧拉函数)
这样可以累加phi(2~n-1),再乘2,再加上(0,1)(1,0)(1,1)三个点可得答案
#include <cstdio>
#include <algorithm>
#define ll unsigned long long
using namespace std;
const int maxn = 40050;
int n;
ll phi[maxn], ans;
void read(int &a)
{
int f = 1;
char ch = getchar();
a = 0;
while(ch < ‘0‘ || ch > ‘9‘)
{
if(ch == ‘-‘) f = -1;
ch = getchar();
}
while(ch >= ‘0‘ && ch <= ‘9‘)
{
a = a*10 + ch - 48;
ch = getchar();
}
a *= f;
}
void write(ll a)
{
int top = 0;
char ch[50];
if(a < 0)
{
putchar(‘-‘);
a = -a;
}
do {
ch[top++] = a%10 + 48;
a /= 10;
} while(a);
while(top--) putchar(ch[top]);
putchar(‘\n‘);
}
void eulerPhi(int a)//筛法求欧拉函数
{
phi[1] = 1;
for(int i = 2; i <= a; ++i) if(phi[i] == 0)
for(int j = i; j <= a; j += i)
{
if(phi[j] == 0) phi[j] = j;
phi[j] = phi[j] / i * (i-1);
}
}
void init()
{
read(n);
eulerPhi(n);
}
void work()
{
for(int i = 2; i < n; ++i) ans += phi[i];
write(ans * 2 + 3);
}
int main()
{
init();
work();
return 0;
}
原文地址:http://blog.csdn.net/t14t41t/article/details/45504725