zoukankan      html  css  js  c++  java
  • BZOJ 2818 Gcd

           本题考查的知识点主要就是用线性筛法求欧拉函数φ,首先说一下什么是欧拉函数:对正整数n,欧拉函数是少于或等于n的数中与n互质的数的数目。之所以要用线性筛法,是因为它能使我们O(n)的求出值。

           先简要介绍一下线性筛法求欧拉函数φ:(摘自baidu)

    int m[maxn],phi[maxn],p[maxn],pt;//m[i]是i的最小素因数,p是素数,pt是素数个数
     
    int make()
    {
        int k,N=maxn;
        
        phi[1]=1;
        for(int i=2;i<N;i++)
        {
            if(!m[i])//i是素数
            {
                p[pt++]=m[i]=i;
                phi[i]=i-1;
            }
            for(int j=0;j<pt&&(k=p[j]*i)<N;j++)
            {
                m[k]=p[j];
                if(m[i]==p[j])//为了保证以后的数不被再筛,要break
                {
                    phi[k]=phi[i]*p[j];
    /*这里的phi[k]与phi[i]后面的∏(p[i]-1)/p[i]都一样(m[i]==p[j])只差一个p[j],就可以保证∏(p[i]-1)/p[i]前面也一样了*/
                    break;    
                }
                else
                {
                    phi[k]=phi[i]*(p[j]-1);//积性函数性质,f(i*k)=f(i)*f(k)
                }
            }
        }
    }

           之后就好做多了求出φ的前缀和乘2再减1,就好了,减得是(1,1)多算的。

    这道题的代码如下:

    #include<cstdio>
    #include<cstdlib> 
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
     
    using namespace std;
     
    typedef long long ll;
    const ll maxn=10000005;
     
    ll i_number,m;
    ll f[maxn],b[maxn],p[maxn];
       
    int main()
    {
        cin>>i_number;
        f[1]=1;
        for(ll i=2;i<=i_number;i++)
        {
            if(!b[i])
            {
                p[m++]=i;
                f[i]=i-1;
            }
             
            for(ll j=0;j<m&&p[j]*i<=i_number;j++)
            {
                f[p[j]*i]=f[i]*p[j];
                b[p[j]*i]=1;
                if(!(i%p[j])) break;
                f[p[j]*i]=(p[j]-1)*f[i];
            }
        }
        
        ll i_temp=0;
        
        for(ll i=1;i<=i_number;i++)
        {
            f[i]=f[i]+f[i-1];
        }  
        for(ll i=1;i<=i_number;i++)
        {
            f[i]=f[i]*2-1;
        }  
        for(ll i=0;i<m;i++)
        {
            i_temp=i_temp+f[i_number/p[i]];
        }  
        
       cout<<i_temp<<endl;
        
       return 0;
    }
    感谢各位观看我的博客,希望对您有所帮助,谢谢。
  • 相关阅读:
    win10如何在局域网中设置一台电脑的固定ip地址
    智能电视软件安装(WIFI上网)
    路由器连接宽带(成功上网步骤方法)
    FastReport.Net使用:[5]主从表
    FastReport.Net使用:[4]分组
    FastReport.Net使用:[3]简单报表一
    FastReport.Net使用:[2]添加MSSQL数据源一
    FastReport.Net使用:[1]屏蔽打印对话框
    如何配置FastReport.Net环境
    如何安装使用FastReport
  • 原文地址:https://www.cnblogs.com/szy-wlxy/p/4699726.html
Copyright © 2011-2022 走看看