zoukankan      html  css  js  c++  java
  • MillerRabin + poLLardrho 模板

     详见:《算法导论》

    HDU 4344

    1、长度是N的因子(且大于1小于N,集合中的元素得两两互质 

    2、为了尽可能多的选出,每个L的质因子应当只包含N的一个质因子,L是一个质因子的整数次,所以K的值就是N中不同质因子的个数

    3、要想和最大,那么使得每个L最大,只要使得质因子的指数最大即可

    所以用pollard_rho分解N的质因数,然后统计不同的质因子个数K,以及计算所有相同质因子乘积的和S

    特殊情况:如果N本身是某个质数的整数i次幂,那么K只能等于1,因为L要小于N,所以L最大为该质数的i-1次幂

    以前poj上用过这个模板。。。放在这道题上wa到爆了。。。最后发现是没注意上面这种情况。。。

    吐嘈一下,恶心的HDOJ,不能用lld。。。。!!

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    #include <string>
    #include <set>
    #include <ctime>
    #include <queue>
    #include <map>
    #include <sstream>
    
    #define CL(arr, val)    memset(arr, (val), sizeof(arr))
    #define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
    #define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
    #define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
    #define L(x)    (x) << 1
    #define R(x)    (x) << 1 | 1
    #define MID(l, r)   ((l) + (r)) >> 1
    #define Min(x, y)   (x) < (y) ? (x) : (y)
    #define Max(x, y)   (x) < (y) ? (y) : (x)
    #define E(x)    (1 << (x))
    #define iabs(x)  ((x) > 0 ? (x) : -(x))
    
    typedef long long LL;
    const double eps = 1e-8;
    //const int inf = ~0u>>2;
    
    using namespace std;
    
    const int C = 16381;
    const LL inf = 1<<22;
    
    
    map<LL, LL> mp;
    
    LL gcd(LL a, LL b) {
        return b ? gcd(b, a%b) : a;
    }
    
    LL mod_mul(LL a, LL b, LL n) {
        LL res = 0;
        while(b > 0) {
            if(b&1)    {res = (res + a); if(res >= n)   res -= n;}
            a = (a + a); if(a >= n) a -= n;
            b >>= 1;
        }
        return res;
    }
    
    LL mod_exp(LL a, LL b, LL n) {
        LL res = 1;
        while(b > 0) {
            if(b&1)    res = mod_mul(res, a, n);
            a = mod_mul(a, a, n);
            b >>= 1;
        }
        return res;
    }
    
    bool miLLer_rabin(LL n) {
        if(n == 2 || n == 3 || n == 5 || n == 7 || n == 11)    return true;
        if(n == 1 || !(n%2) || !(n%3) || !(n%5) || !(n%7) || !(n%11))    return false;
    
        LL x, pre, u;
        int i, j, k = 0;
        u = n - 1;
    
        while(!(u&1)) {
            k++; u >>= 1;
        }
        srand((LL)time(0));
        for(i = 0; i < 5; ++i) {    //5次足够AC了
            x = rand()%(n-2) + 2;
            if((x%n) == 0)    continue;
            x = mod_exp(x, u, n);
            pre = x;
            for(j = 0; j < k; ++j) {
                x = mod_mul(x, x, n);
                if(x == 1 && pre != 1 && pre != n-1)    return false;
                pre = x;
            }
            if(x != 1)    return false;
        }
        return true;
    }
    
    LL poLLard_rho(LL n, LL c) {
        LL x, y, d;
        LL i, k;
        i = 1; k = 2;
    
        srand((LL)time(0));
        x = rand()%(n-1) + 1;
        y = x;
    
        while(1) {
            i ++;
            x = (mod_exp(x, 2, n) + c) % n;
            d = gcd(y - x + n, n);
            if(d != 1 && d != n)    return d;
            if(x == y)    return n;
            if(i == k) {
                y = x; k *= 2;
            }
        }
    }
    
    void factor(LL n, LL c) {
        if(n <= 1)    return ;
        LL r, d;
        if(miLLer_rabin(n)) {
            if(mp[n] == 0)  mp[n] = n;
            else    mp[n] *= n;
            return ;
        }
        r = poLLard_rho(n, c--);
        d = n/r;
        factor(d, c);
        factor(r, c);
    }
    
    int main() {
        //freopen("data.in", "r", stdin);
    
        int t;
        LL n, k, sum;
        scanf("%d", &t);
        while(t--) {
            cin >> n;
            if(miLLer_rabin(n))    {cout << 1 << " " << 1 << endl;}
            else {
                sum = 0; k = 0;
                mp.clear();
                factor(n, C);
                map<LL, LL>::iterator it;
    
                for(it = mp.begin(); it != mp.end(); ++it) {
                    k++; sum += it->second;
                }
                it = mp.begin();
                if(k == 1)  cout << k << " " << sum/it->first << endl;
                else    cout << k << " " << sum << endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    Java IO6:字符流进阶及BufferedWriter、BufferedReader
    Java IO5:字符流
    Java IO4:字符编码
    Java IO3:字节流
    Java IO2:RandomAccessFile
    Java IO1:IO和File
    Java异常
    Java语法糖4:内部类
    SharePoint JavaScript API 根据文件路径删除文件
    SharePoint PowerShell 批量删除遗弃视图
  • 原文地址:https://www.cnblogs.com/vongang/p/2629047.html
Copyright © 2011-2022 走看看