zoukankan      html  css  js  c++  java
  • 2020 China Collegiate Programming Contest, Weihai Site D. ABC Conjecture(唯一分解定理/Pollard Rho)

    ABC Conjecture Time limit: 3 seconds Figure 1: Shinichi Mochizuki The ABC conjecture (also known as the Oesterle–Masser conjec- ´ ture) is a famous conjecture in number theory, first proposed by Joseph Oesterle and David Masser. It is formally stated as follows: ´ For every positive real number ε, there are only finitely many positive integer triples (a, b, c) such that 1. a and b are relatively prime; 2. a + b = c; and 3. c > rad(abc) 1+ε , where rad(n) = Y p|n p∈Prime p is the product of all distinct prime divisors of n. Shinichi Mochizuki claimed to have proven this conjecture in August 2012. Later, Mochizuki’s claimed proof was announced to be published in Publications of the Research Institute for Mathematical Sciences (RIMS), a journal of which Mochizuki is the chief editor. Spike is a great fan of number theory and wanted to prove the ABC conjecture as well. However, due to his inability, he turned to work on a weaker version of the ABC conjecture, which is formally stated as follows: Given a positive integer c, determine if there exists positive integers a, b, such that a + b = c and rad(abc) < c. Note that in the original ABC conjecture, the positive integers a and b are required to be relatively prime. However, as Spike is solving an easier version of the problem, this requirement is removed. Input The first line of input contains one integer T (1 ≤ T ≤ 10), the number of test cases. The next lines contain description of the t test cases. Each test case contains one line, including an integer c (1 ≤ c ≤ 1018). Output For each test case, if there exist two positive integers a, b satisfying a + b = c and rad(abc) < c, then output yes in a line, otherwise output no instead.

    Example

    standard input

    3

    4

    18

    30

    standard output

    yes

    yes

    no

    首先如果c是质数的话肯定不行,然后考虑把c唯一分解:(c = p_1^{x_1}p_2^{x_2}...p_k^{x_k})。考虑rad函数的性质,就会发现如果每个质数的次数都为1肯定也不行,因为此时rad(c) = c,rad(abc)大于等于c,不满足要求。那么c的某个质因子的次数至少为2,设(c = p_1^{2}x),则可以令(a = p_1x,b=(1-p_1)p_1x),则(rad(abc) = rad(p_1x(1-p_1)p_1xp_1x)=rad((1-p_1)p_1x)),又因为((1-p_1)p_1x < {p_1}^2x = c),因此 (rad((1-p_1)p_1x) < c)。故此时直接输出yes即可。

    由于范围到了1e18,因此需要用Pollard Rho进行大数唯一分解。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 1e5+16;
    LL n, x,y,a[maxn];
    struct BigIntegerFactor{
        const static int maxm = 1e6+16;
        LL prime[maxm],p[maxm],fac[maxm],sz,cnt;     //多组输入注意初始化cnt = 0
        inline LL mul(LL a,LL b,LL mod){             //WA了尝试改为__int128或慢速乘
            if(mod <= 1000000000) return a * b % mod;
            return (a*b-(LL)((long double)a/mod*b+1e-8)*mod+mod)%mod;
        }
        void init(int maxn){
            int tot = 0; sz = maxn-1;
            for(int i = 1;i <= sz; ++i) p[i] = i;
            for(int i = 2;i <= sz; ++i){
                if(p[i] == i) prime[tot++] = i;
                for(int j = 0;j<tot&&1ll*i*prime[j]<=sz; ++j){
                    p[i*prime[j]] = prime[j];
                    if(i%prime[j] == 0) break;
                }
            }
        }
        LL powl(LL a,LL x,LL mod){
            LL res = 1LL;
            while(x){
                if(x&1) res = mul(res,a,mod);
                a = mul(a,a,mod);
                x >>= 1;
            }
            return res;
        }
        bool check(LL a,LL n){                       //二次探测原理检验n
            LL t = 0,u = n-1;
            while(!(u&1)) t++,u >>= 1;
            LL x = powl(a,u,n),xx = 0;
            while(t--){
                xx = mul(x,x,n);
                if(xx==1 && x!=1 && x!=n-1) return false;
                x = xx;
            }
            return xx == 1;
        }
        bool miller(LL n,int k){
            if(n == 2) return true;
            if(n < 2 || !(n&1)) return false;
            if(n <= sz) return p[n] == n;
            for(int i = 0;i <= k; ++i){               //测试k次
                if(!check(rand()%(n-1)+1,n)) return false;
            }
            return true;
        }
        inline LL gcd(LL a,LL b){
            return b == 0 ? a : gcd(b,a%b);
        }
        inline LL Abs(LL x){
            return x < 0 ? -x : x;
        }
        LL Pollard_rho(LL n){                  //基于路径倍增的Pollard_Rho算法
            LL s = 0,t = 0,c = rand()%(n-1)+1,v = 1,ed = 1;
            while(1){
                for(int i = 1; i <= ed; ++i){
                    t = (mul(t,t,n) + c) % n; v = mul(v,Abs(t-s),n);
                    if(i % 127 == 0){
                        LL d = gcd(v,n);
                        if(d > 1) return d;
                    }
                }
                LL d = gcd(v,n); if(d > 1) return d;
                s = t; v = 1; ed <<= 1;           
            }
        }
        void getfactor(LL n){                          //得到所有的质因子(可能有重复的)
            if(n <= sz){
                while(n != 1) fac[cnt++] = p[n],n /= p[n];
                return;
            }
            if(miller(n,6)) fac[cnt++] = n;
            else{
                LL d = n; while(d >= n) d = Pollard_rho(n);
                getfactor(d); getfactor(n/d);
            }
        }
        LL cal(LL n,LL x){                            //计算 n! 中质因子 x 的数量
            LL num = 0;
            while(n){
                num += n/x;
                n = n/x;
            }
            return num;
        }
        bool judge(LL x) {
            //cnt = 0; getfactor(x);
            //因为必定先判断素数 这时候的cnt已经计算出来了 因此这里不用再计算一遍 也无需再清空
            map<LL, LL> mp;
            for(int i = 0;i < cnt; ++i) {
                if(mp.find(fac[i]) != mp.end()) return 0;
                mp[fac[i]]++;
            }
            return 1;
        }
        bool isPrime(LL x) {
            cnt = 0; getfactor(x);
            if(cnt == 1) return 1;
            else return 0;
        }
    }Q;
    
    int main() {
    	int t;
    	cin >> t;
        Q.init(200000);
    	while(t--) {
    		long long c;
            scanf("%lld", &c);
            if(Q.isPrime(c)) {
                cout << "no" << endl;
            } else {
                bool allone = Q.judge(c);//判断c的所有质因子的次数是否都为1
                if(allone) cout << "no" << endl;
                else {
                    cout << "yes" << endl;
                }
            }
    		
    	}
    	return 0;
    }
    
  • 相关阅读:
    批量SSH操作工具---OmniTTY安装
    CentOS6.6修改主机名和网络信息
    浪潮服务器通过ipmitool获取mac地址
    linux批量执行工具omnitty使用方法
    操作系统下查看HBA卡信息wwn的方法
    Linux下multipath多路径配置
    IPMITOOL 配置BMC用户设置
    第五讲 对于耦合的认识 target/action设计模式 delegate设计模式 手势识别器
    UI第四讲.事件处理(按钮点击切换视图,触摸事件)
    UI第三讲.自定义视图 视图控制器 检测屏幕旋转
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14756404.html
Copyright © 2011-2022 走看看