码迷,mamicode.com
首页 > 其他好文 > 详细

Sdoi2008仪仗队题解

时间:2015-05-05 19:42:50      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:数论   欧拉函数   

题目描述 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 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;
}

Sdoi2008仪仗队题解

标签:数论   欧拉函数   

原文地址:http://blog.csdn.net/t14t41t/article/details/45504725

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!