• [SDOI2008]仪仗队(欧拉筛裸题)


    题目描述

    作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如右图)。  现在,C君希望你告诉他队伍整齐时能看到的学生人数。

    输入输出格式

    输入格式:

    共一个数N

    输出格式:

    共一个数,即C君应看到的学生人数。

    思路:

    典型的欧拉筛

    为了帮助萌新,我先从欧拉函数开讲

    什么是欧拉函数?

    定义:与一个数的约数有且只有1的数(互质)的个数(比如说2有1一个,6有1,5两个)

    性质:积性函数(Phi(i)等于他的所有质因数的phi值的乘积)

    为什么能这么做呢?

    其实这道题求的是有多少种不同的斜率

    为什么呢?

    看图:

    很显然,一个斜率上只能看到一个人,该斜率其他人都会被堵得死死的。。。

    那么,每一个独立的斜率又如何表示呢?

    我们用数对(x,y)表示斜率

    我们知道,如果x,y不互质,那么他们可以同时除以他们的最大公约数(设为k),则该斜率可表示为(x/k,y/k)

    很显然会有重复

    所以为了避免重复,我们所求的是互质点对的个数

    互质点对很显然就是欧拉函数

    这里我用的是(nlogn)的算法——埃氏筛

    从2开始,一个数i如果因数标记为1,则他是素数,他的欧拉函数值为i-1,同时,利用它来更新所有它的倍数的因数标记,如果因数标记大于1,则其不是素数,根据积性函数的性质,Phi[i]=其各因数的乘积,当其含有多次方因子时(比如8=2^3),那么Phi[i]的值为phi[2]*2*2;

    不说了,代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    long long ll;
    long long e[40010];
    long long n,ans;
    int main()
    {
        ans=2;
        cin>>n;
        if(n==1)
        {
            cout<<0;
            return 0;
        }
        for(int i=1;i<=n;++i)
        {
            e[i]=i;
        }
        for(int i=2;i<=n;++i)
        {
            if(e[i]==i)
            {
                for(int j=i;j<=n;j+=i)
                {
                    e[j]=e[j]/i*(i-1);
                }
            }
        }
        n--;
        for(int i=2;i<=n;++i)
        {
            ans+=e[i]*2;
        }
        cout<<ans+1;
    }        
  • 相关阅读:
    Java在Web开发语言上败给了PHP(转)
    很开心收到了Andreas Loew发给我的注册key
    Cocos2d-x开发移植到安卓平台横竖屏设置及相关
    学习实战二:利用Cocos2d-x写的第一个游戏
    Cocos2d-x项目移植到安卓平台易出现的错误
    cocos2d-x帧动画实现(写下备忘)
    cocos2d-x学习遇到的问题
    C++指针的管理
    Win7开自带的虚拟WIFI
    【SICP练习】21 练习1.27
  • 原文地址:https://www.cnblogs.com/ztz11/p/9059526.html
Copyright © 2020-2023  润新知