• 数论


    #pragma warning (disable: 4786)
    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<deque>
    #include<map>
    #include<algorithm>
    using namespace std;
    
    #ifdef _WIN32
    typedef unsigned __int64 UINT64;
    #elif
    typedef unsigned long long UINT64;
    #endif
    
    //1000以内素数表
    UINT64 gPrimeTable1000[] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,
        101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,
        211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,
        337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,
        461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,
        601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,
        739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,
        881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997};
    
    /******************************************************************************
                             数论类
    ******************************************************************************/
    class Number
    {
    public:
        Number(UINT64 n=0) : num(n) {} //构造函数
        void print (ostream& oo) const; //打印
        static Number rand(); //随机数
    
        //基本运算
        bool    operator == (const Number& n) const {return num == n.num;}
        bool    operator != (const Number& n) const {return num != n.num;}
        bool    operator >  (const Number& n) const {return num > n.num;}
        bool    operator <  (const Number& n) const {return num < n.num;}
        bool    operator >= (const Number& n) const {return num >= n.num;}
        bool    operator <= (const Number& n) const {return num <= n.num;}
        Number  operator +  (const Number& n) const {return num + n.num;}
        Number  operator -  (const Number& n) const {return num - n.num;}
        Number  operator *  (const Number& n) const {return num * n.num;}
        Number  operator /  (const Number& n) const {return num / n.num;}
        Number  operator %  (const Number& n) const {return num % n.num;}
        Number& operator += (const Number& n) {num += n.num; return *this;}
        Number& operator -= (const Number& n) {num -= n.num; return *this;}
        Number& operator *= (const Number& n) {num *= n.num; return *this;}
        Number& operator /= (const Number& n) {num /= n.num; return *this;}
        Number& operator %= (const Number& n) {num %= n.num; return *this;}
    
        bool isPrime() const; //是否素数
        Number power(unsigned int index) const; //
        Number powerModule(Number index, Number mod) const; //幂余
        void factorization(map<Number,int>& factor) const; //因子分解
        Number primeNumber(Number n) const;  //n以内素数个数
        Number eulerFunc() const; //Euler函数φ
        Number mobiusFunc() const; //M?bius函数μ
        int legendre(Number p) const; //Legendre符号, 二次剩余, p必须是素数
        static Number gcd(Number a, Number b); //最大公约数
        static Number gcd(Number a[], int n); //一组数的最大公约数
        static void primeTable(int n, deque<Number>& table); //素数表
        static Number fabonacci(int n); //Fabonacci数
        static Number combinatory(unsigned int n, unsigned int m);
        static Number permutation(unsigned int n, unsigned int m);
    
        Number RSA_encryption(Number r, Number e);
        Number RSA_decryption(Number r, Number d);
    private:
        Number powerForIsPrime(Number a, Number p) const; //isPrime的辅助函数,幂余的时候加二次探测
        Number pollard() const; //Pollard法求一个因子
    public:
        UINT64 num;
    };
    
    ostream& operator << (ostream& oo,Number& n) //重载插入运算符
    {
        n.print(oo);
        return oo;
    }
    
    void Number::print(ostream& oo) const
    {
    #ifdef _WIN32
        printf("%I64u",num);
    #elif
        printf("%llu",num);
    #endif
    }
    
    Number Number::rand()
    {
        return Number(UINT64(::rand()) * ::rand() * ::rand() * ::rand());
    }
    
    Number Number::power(unsigned int index) const
    {
        Number ans = 1;
        Number pow = num;
    
        while (index)
        {
            if (index & 1)
                ans.num *= pow.num;
            pow.num *= pow.num;
            index >>= 1;
        }
    
        return ans;
    }
    
    Number Number::powerModule(Number index, Number mod) const
    {
        Number r = 1;
        Number pow = num;
    
        while (index.num)
        {
            if (index.num & 1)
                r.num = r.num * pow.num % mod.num;
            pow.num = pow.num * pow.num % mod.num;
            index.num >>= 1;
        }
    
        return r;
    }
    
    Number Number::powerForIsPrime(Number a, Number p) const
    {
        if (p == 0)
            return 1;
        Number x = powerForIsPrime(a, p/2);
        Number result = x*x % num; //二次探测
        if (result == 1 && x != 1 && x != num-1) //若num为素数, 则方程x^2≡1的解为x=1或p-1
            return 0; //是合数
        if (p%2 == 1)
            result = result * a % num;
        return result;
    }
    
    bool Number::isPrime() const
    {
        if (num <= 1000)
            return find(gPrimeTable1000,gPrimeTable1000+168,num) != gPrimeTable1000+168;
    
        for (int time=1; time<10; time++)
        {
            Number a = rand()%(num-3) + 2;
            Number result = powerForIsPrime(a, num-1); //Fermart小定理
            if (result == 0 || result != 1)
                return false;
        }
        return true;
    }
    
    Number Number::pollard() const
    {
        for (int j=0; j<168; j++)
            if (num % gPrimeTable1000[j] == 0)
                return gPrimeTable1000[j];
    
        Number x = rand() % num;
        Number y = x;
        int k = 2;
        for (int i=2; i<1024; i++)
        {
            x = (x*x - 1) % num;
            Number d = gcd(y-x, num);
            if (d > 1 && d < num)
                return d;
            if (i == k)
            {
                y = x;
                k *= 2;
            }
        }
        return 1;
    }
    
    void Number::factorization(map<Number,int>& factor) const
    {
        if (isPrime())
        {
            factor[num]++;
            return;
        }
    
        Number d;
        for (int t=1; t<=10; t++)
        {
            d = pollard();
            if (d.num != 1)
                break;
        }
        if (d.num == 1)
            return;
    
        d.factorization(factor);
        (*this/d).factorization(factor);
    }
    
    Number Number::eulerFunc() const
    {
        map<Number,int> factor;
        factorization(factor);
        Number ans = num;
        for (map<Number,int>::const_iterator it=factor.begin(); it!=factor.end(); ++it)
            ans = ans * (it->first-1) / it->first;
        return ans;
    }
    
    Number Number::mobiusFunc() const
    {
        if (num == 1)
            return 1;
    
        map<Number,int> factor;
        factorization(factor);
        for (map<Number,int>::const_iterator it=factor.begin(); it!=factor.end(); ++it)
            if (it->second > 1)
                return 0;
    
        if(factor.size() % 2 == 0)
            return 1;
        else
            return -1;
    }
    
    int Number::legendre(Number p) const
    {
        if (num % p.num == 0)
            return 0;
        else if (powerModule((p-1)/2, p) == 1)
            return 1;
        else
            return -1;
    }
    
    Number Number::gcd(Number a, Number b)
    {
        UINT64 r;
        while (b != 0)
        {
            r = a.num % b.num;
            a.num = b.num;
            b.num  = r;
        }
        return a;
    }
    
    Number Number::gcd(Number a[], int n)
    {
        if (n < 2)
            return 1;
        Number d = gcd(a[0], a[1]);
        for (int i=2; i<n; i++)
            d = gcd(d, a[i]);
        return d;
    }
    
    void Number::primeTable(int n, deque<Number>& table)
    {
        for (int i=3; i<n; i+=2)
        {
            int j;
            for (j=0; j<table.size(); j++)
                if (i % table[j].num == 0)
                    break;
            if (j == table.size())
                table.push_back(i);
        }
        table.push_front(2);
    }
    
    Number Number::combinatory(unsigned int n, unsigned int m)
    {
        if (m > n)
            return 0;
        UINT64 ans = 1;
        for (int i=0; i<m; i++)
            ans = (ans * (n-i)) / (i+1);
        return ans;
    }
    
    Number Number::permutation(unsigned int n, unsigned int m)
    {
        if (m > n)
            return 0;
        UINT64 ans = 1;
        for (int i=0; i<m; i++)
            ans *= (n-i);
        return ans;
    }
    
    //RSA加密
    //r=p*q为两个大素数的乘积, e与(p-1)*(q-1)互素为明文
    Number Number::RSA_encryption(Number r, Number e)
    {
        return powerModule(e,r);
    }
    
    //RSA解密
    //r=p*q为两个大素数的乘积, d为密文, d*e≡1 (mod (p-1)*(q-1))
    Number Number::RSA_decryption(Number r, Number d)
    {
        return powerModule(d,r);
    }
  • 相关阅读:
    python基础之函数
    MySQL 安装 5.0
    MySQL安装 MySQL5.7.10免安装版配置,mysql5.7.10免安装版
    安装MYSql Windows7下MySQL5.5.20免安装版的配置
    网站集合
    andorid 开放工具集合
    Win7 x64 Eclipse无法识别手机 / adb interface有黄色感叹号,无法识别
    字符集 ISO-8859-1(3)
    字符集 ISO-8859-1(2)
    字符集 ISO-8859-1(1)
  • 原文地址:https://www.cnblogs.com/saieuler/p/2775741.html
Copyright © 2020-2023  润新知