zoukankan      html  css  js  c++  java
  • [俺们学校的题]伪.GCD

    GCD

    题面:

      给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对.

    思路:

      首先两个数gcd(x,y)=p为质数,那么令x=k1*p,y=k2*p,由于是最大公因数,所以有k1k2互质,那么根据每一个p我们可以构造出一些不同的k1k2(k1,k2<=n/p),于是求k1,k2可行组合就变成了求 1~n/p范围之内的互质组数。我们运用欧拉筛同时解决找p和互质组数的问题

      首先解决互质组数的问题。我们设f[i]为1~i中的互质二元组个数。则有递推式:

      f[i]=f[i-1]+2*φ(i)

      因为1~i-1我们已经计算过了,所以考虑当前的i与1~i之间组成的互质二元组个数。很显然的,个数为φ(i).欧拉筛求解。由于二元组无序,所以*2

      在欧拉筛的时候,可以同时求出质数p和φ(i).所以求出答案。

      注意在欧拉筛是从2开始,所以初始化f[1]=1;

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<fstream>
    using namespace std;
    #define ll long long
    ll phi[10000001],prm[10000001],n,cnt,f[10000001];
    bool vis[10000001];
    inline void findphi(){
        phi[1]=1,prm[1]=0;
        for (ll i=2;i<=n;++i)
        {
            if (!vis[i]) { prm[++cnt]=i, phi[i]=i-1; }
            for (ll j=1;j<=cnt && i*prm[j]<=n;++j)
            {
                vis[i*prm[j]]=1;
                if (i%prm[j]==0) { phi[i*prm[j]]=phi[i]*prm[j]; break; }
                if (i%prm[j]!=0) phi[i*prm[j]]=phi[i]*(prm[j]-1);   
            }
            f[i]=f[i-1]+2*phi[i];
        }
        return; 
    }
    int main(){
        cin>>n;
        cnt=0;
        f[1]=1;
        findphi();
        ll ans=0;
        for(int i=1;i<=cnt;++i){
            ans+=f[n/prm[i]];
        }
        cout<<ans;    
    }
  • 相关阅读:
    innodb文件
    Innodb 存储引擎
    第二章 flex输入输出结构
    第二章 flex输入输出
    第二章 flex处理二义性
    第一章 flex单词计数程序
    Compile SQLite3 from individual files
    标 题: [心得]传统IT转互联网面试经验分享
    【设计模式】二:策略模式
    python 爬虫第三例--爬美女图片
  • 原文地址:https://www.cnblogs.com/clockwhite/p/12077566.html
Copyright © 2011-2022 走看看