• BZOJ-2190 仪仗队 数论+欧拉函数(线性筛)


    今天zky学长讲数论,上午水,舒爽的不行。。后来下午直接while(true){懵逼;}死循全程懵逼。。。。(可怕)Thinking Bear。
    

    2190: [SDOI2008]仪仗队
    Time Limit: 10 Sec Memory Limit: 259 MB
    Submit: 2092 Solved: 1325
    [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
    数论

    这道题啊,算是我懵逼过程中最水的题了。。于是下课 顺利一遍水过(哦,第一次复制错了。。。CE。。不算!)
    

    这道题,先小数据捯饬捯饬。。发现了规律:
    1.除了坐标带0的点,其他的点都满足gcd(x,y)=1,所以累加欧拉函数φ。。然后加上坐标带0的点即可(2个,一成不变)。。
    2.然后发现具有对称性。。于是只需要搞上方的三角即可。但是对角线那个点重复了一次所以-1

    于是 ans=Σ(φ【1..n-1】)*2+1(+1其实是+2-1)
    ps(程序里,欧拉函数的处理没有处理φ【1】所以有个初始值。。思路一样。。)

    那么就是筛出欧拉函数即可。。(根据性质:)
    性质① m是素数时,有φ(m)=m-1
    性质② 当m、n互素时,φ(m*n)=φ(m)*φ(n)
    性质③ 对一切正整数n,有φ(p^n)=[p^(n-1)]*(p-1)

    奇怪的代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 40010
    long long prime[maxn],phi[maxn];
    bool flag[maxn]={0};
    int n;
    long long ans;
    
    void get_phi()
    {
        memset(flag,0,sizeof(flag));
        flag[1]=1; 
        int cnt=0;
        for (int i=2; i<=maxn; i++)
            {
                if (!flag[i])
                    prime[cnt++]=i,phi[i]=i-1;
                for (int j=0; j<cnt && i*prime[j]<maxn; j++)
                    {
                        flag[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);
                    }
            }
    }
    
    int main()
    {
        scanf("%d",&n);
        get_phi();
        ans=2; 
        for (int i=2; i<n; i++)
            ans+=phi[i];
        printf("%lld",ans*2-1);
        return 0;
    }
  • 相关阅读:
    Iview多行表单增删、表单校验
    Linux常用命令+Git命令
    前端架构师图谱
    第八章学习心得
    第七章学习心得
    第6章学习心得
    第5章学习总结
    第四章心得体会
    第三章学习心得
    第二章学习心得
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346205.html
Copyright © 2020-2023  润新知