zoukankan      html  css  js  c++  java
  • poj2773(欧基里德算法 或 二分+容斥)

    题目链接:https://vjudge.net/problem/POJ-2773

    题意:给定m,k,求与m互质的第k个数。

    思路一:利用gcd(a,b)=gcd(b*t+a,b)知道,与m互质的数是以m为周期分布的,这样可以先枚举小于m的所有与m互质的数,利用周期就可以得到第k小的数了,这样复杂度为O(T*m),比较大,但也能过,2439ms,代码实现相对简单。

    AC代码:

    #include<cstdio>
    using namespace std;
    
    int gcd(int a,int b){
        return b?gcd(b,a%b):a;
    }
    
    int m,k,a[1000005],cnt;
    
    int main(){
        while(~scanf("%d%d",&m,&k)){
            cnt=0;
            for(int i=1;i<=m;++i)
                if(gcd(i,m)==1)
                    a[++cnt]=i;
            printf("%d
    ",((k-1)/cnt)*m+a[(k-1)%cnt+1]);
        }
        return 0;
    }

    思路二:一般看到求第k个数可以想到二分思想,我们可以在int范围内二分答案,每次二分到mid时,要得到[1,mid]区间内与m互质的数的个数才行。求与m互质的数的个数,很明显求不互质的数的个数要方便,可以通过容斥转换为计算[1,mid]中与m不互质的数的个数,即通过枚举m的所有约数(预先通过唯一分解定理打表得到m的所有质因数,设有cnt个质因数,然后就有2^cnt-1个约数组合),通过约数中质因数数目的奇偶决定加或减即可,复杂读小很多。0ms通过。

    AC代码:

    #include<cstdio>
    using namespace std;
    typedef long long LL;
    
    int m,k,cnt,fac[50],ans;
    
    void init(){
        cnt=0;
        int tmp=m;
        for(int i=2;i*i<=m;++i)
            if(tmp%i==0){
                fac[cnt++]=i;
                while(tmp%i==0) tmp/=i;
            }
        if(tmp!=1) fac[cnt++]=tmp;
    }
    
    int getnum(int x){
        int ret=x;
        for(int i=1;i<(1<<cnt);++i){
            int t1=1,t2=0;
            for(int j=0;j<cnt;++j)
                if(i&(1<<j))
                    t1*=fac[j],++t2;
            if(t2&1) ret-=x/t1;
            else ret+=x/t1;
        }
        return ret;
    }
    
    int main(){
        while(~scanf("%d%d",&m,&k)){
            init();
            int l=1,r=2147483647,mid;
            while(l<=r){
                mid=(l+r)>>1;
                int tmp=getnum(mid);
                if(tmp<k) l=mid+1;
                else if(tmp>k) r=mid-1;
                else
                    ans=mid,r=mid-1;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    SVN服务器搭建(一)
    排序算法二:冒泡排序
    【LeetCode】136. Single Number
    【LeetCode】217. Contains Duplicate
    【LeetCode】189. Rotate Array
    【LeetCode】122. Best Time to Buy and Sell Stock II
    【LeetCode】26. Remove Duplicates from Sorted Array
    【LeetCode】20. Valid Parentheses
    【LeetCode】680. Valid Palindrome II
    【LeetCode】345. Reverse Vowels of a String
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/10828543.html
Copyright © 2011-2022 走看看