数论--合数

将合数进行质因数分解的方式
第一种:试除法;
第二种:Pollard_rho 算法;

第一种
原理:通过预先建立的素数表,遍历素数表将所有的质因数记录并存下来

/*
 *  合数的分解需要先进行素数的筛选
     得到prime[]素数表 
 *  factor[i][0]存放分解的素数
 *  factor[i][1]存放对应素数出现的次数
 *  fatCnt存放合数分解出的素数个数(相同的素数只算一次)
 */
long long factor[100][2];
int fatCnt;
//  合数分解
int getFactors(long long x)
{
    fatCnt = 0;
    long long tmp = x;
    for (int i = 1; prime[i] <= tmp / prime[i]; i++)
    {
        factor[fatCnt][1] = 0;
        if (tmp % prime[i] == 0)
        {
            factor[fatCnt][0] = prime[i];
            while (tmp % prime[i] == 0)
            {
                factor[fatCnt][1]++;
                tmp /= prime[i];
            }
            fatCnt++;
        }
    }
    if (tmp != 1)
    {
        factor[fatCnt][0] = tmp;
        factor[fatCnt++][1] = 1;
    }
    return fatCnt;
}

第二种:
原理:玄学?(没搞懂)
作用:高效的质因数分解

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxm=2e5+5;
ll temp[maxm],cnt;//存所有质因子
set<int>st;
//板子:
ll gcd(ll a, ll b) {
    return b ? gcd(b, a % b) : a;
}//求最大公约数 
ll quick_mult(ll a, ll b, ll mod) {
    ll ans = 0;
    while(b) {
        if(b & 1) ans = (ans + a) % mod;
        a = (a + a) % mod;
        b >>= 1;
    }
    return ans;
}//快速乘法 
ll quick_pow(ll a, ll n, ll mod) {
    ll ans = 1;
    while(n) {
        if(n & 1) ans = quick_mult(ans, a, mod);
        a = quick_mult(a, a, mod);
        n >>= 1;
    }
    return ans;
}//快速幂 
bool miller_rabin(ll n) {
    if(n == 2) return true;
    if(n < 2 || !(n & 1)) return false;
    ll s = 0, d = n - 1;
    while(!(d & 1)) {
        d >>= 1;
        s++;
    }
    for(int i = 1; i <= 11; i++) {
        ll a = rand() % (n - 2) + 2;
        ll now = quick_pow(a, d, n), pre = now;
        for(int j = 1; j <= s; j++) {
            now = quick_mult(now, now, n);
            if(now == 1 && pre != 1 && pre != n - 1) return false;
            pre = now;
        }
        if(now != 1) return false;
    }
    return true;
}//判断n是否为素数 
ll pollard_rho(ll n, int c) {
    ll x, y, i = 1, k = 2;
    x = y = rand() % (n - 2) + 2;
    for( ; ; ) {
        i++;
        x = (quick_mult(x, x, n) + c) % n;
        ll g = gcd(y - x, n);
        if(g > 1 && g < n) return g;
        if(x == y) return n;
        if(i == k) y = x, k <<= 1;
    }
}//求出n的一个因数 c自己写的 玄学的地方  
void find_fac(ll n, int k) {
    if(n == 1) return ;
    if(miller_rabin(n)) {
        st.insert(n);
        temp[n]++;
        return ;
    }
    ll p = n;
    int c = k;
    while(p >= n) p = pollard_rho(p, c--);
    find_fac(p, k);
    find_fac(n / p, k);
}//set里装的是质因数 temp里装的是幂 k和上面的c一样 玄学 
//
int main(){

 ll n;
 cin>>n;
 find_fac(n,107);
 set<int>::iterator it;
for(it=st.begin();it!=st.end();it++)
{
    cout<<*it<<"^"<<temp[*it]<<endl;
}
    return 0;
}

全部评论

相关推荐

10-14 23:01
已编辑
中国地质大学(武汉) Java
CUG芝士圈:虽然是网上的项目,但最好还是包装一下,然后现在大部分公司都在忙校招,十月底、十一月初会好找一些。最后,boss才沟通100家,别焦虑,我去年暑假找第一段实习的时候沟通了500➕才有面试,校友加油
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务