Sdoi2008仪仗队题解

来源:互联网 发布:数据离差标准化 编辑:程序博客网 时间:2024/05/17 01:42

题目描述 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)三个点可得答案

  • Code:
#include <cstdio>#include <algorithm>#define ll unsigned long longusing 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;}
0 0
原创粉丝点击