数论--合数
将合数进行质因数分解的方式
第一种:试除法;
第二种: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;
}
查看8道真题和解析