大素数判定以及大整数分解

素数判定——Miller Rabin 算法

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#define ll long long
#include <map>
using namespace std;

ll ksc(ll a,ll b,ll c) {
    
    
	a%=c;
	b%=c;
	ll ret=0;
	ll tmp=a;
	while(b) {
    
    
		if(b&1) {
    
    
			ret+=tmp;
			if(ret>c) ret-=c;//直接取模慢很多 
		}
		tmp<<=1;
		if(tmp>c) tmp-=c;
		b>>=1;
	}
	return ret;
} 

ll ksm(ll a, ll b, ll mod) {
    
    
	ll ans = 1;
	while(b) {
    
    
		if(b & 1) ans = ksc(ans, a, mod);
		a = (ksc(a, a, mod)) % mod;
		b >>= 1;
	}
	return ans % mod;
}

bool MillerRabin(ll p) {
    
    
	ll x, pre, u = p - 1; //  pre 记录x  自乘前的数
	if(p==2||p==3||p==5||p==7||p==11) return true;
    if(p==1||!(p%2)||!(p%3)||!(p%5)||!(p%7)||!(p%11)) return false; 
    int i = 0, j = 0, k = 0;
    while(!(u & 1)) {
    
    
    	k++;
    	u >>= 1;
	}
	srand((ll)12234336);
	for(i = 1; i <= 50; i++) {
    
    
		x = rand() % (p - 2) + 2; // 生成该范围的数
		if(!(p % x)) return false; 
		x = ksm(x, u, p);
		pre = x;
		for(j = 1; j <= k; j++) {
    
    
			x = ksc(x, x, p);
			if(x == 1 && pre != 1 && pre != p - 1) return false;
			pre = x;
		}
		if(x !=1 ) return false;
	}
	return true;
}

int main() {
    
    
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << MillerRabin(100001399) << endl;
	
	return 0;
}

大整数分解

整数分解 easy

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#define ll long long
#include <map>
using namespace std;

ll ksc(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 % mod;
}

ll ksm(ll a, ll b, ll mod) {
    
    
	ll ans = 1;
	while(b) {
    
    
		if(b & 1) ans = ksc(ans, a, mod);
		a = (ksc(a, a, mod)) % mod;
		b >>= 1;
	}
	return ans % mod;
}

bool MillerRabin(ll p) {
    
    
	ll x, pre, u = p - 1; //  pre 记录x  自乘前的数
	if(p==2||p==3||p==5||p==7||p==11) return true;
    if(p==1||!(p%2)||!(p%3)||!(p%5)||!(p%7)||!(p%11)) return false; 
    int i = 0, j = 0, k = 0;
    while(!(u & 1)) {
    
    
    	k++;
    	u >>= 1;
	}
	srand((ll)12234336);
	for(i = 1; i <= 50; i++) {
    
    
		x = rand() % (p - 2) + 2; // 生成该范围的数
		if(!(p % x)) return false; 
		x = ksm(x, u, p);
		pre = x;
		for(j = 1; j <= k; j++) {
    
    
			x = ksc(x, x, p);
			if(x == 1 && pre != 1 && pre != p - 1) return false;
			pre = x;
		}
		if(x != 1 ) return false;
	}
	return true;
}
ll PollardRho(ll n,ll c) {
    
    
	ll i=1,j=2,x=rand()%(n-1)+1,y=x;//随机初始化一个基数(p1)
	while(1) {
    
    
		i++;
		x=(ksc(x,x,n)+c)%n;//玄学递推
		ll p=__gcd((y-x+n)%n,n);
		if(p!=1&&p!=n)return p;//判断
		if(y==x)return n;//y为x的备份,相等则说明遇到圈,退出
		if(i==j) {
    
    
			y=x;
			j<<=1;
		}//更新y,判圈算法应用
	}
}
void find(ll n,ll c) {
    
     //同上,n为待分解数,c为随机常数
	if(n==1)return;
	if(MillerRabin(n)) {
    
     //n为质数
		//保存,根据不同题意有不同写法,在此略去
		cout << n << ' ';
		return;
	}
	ll x=n,k=c;
	while(x==n)x=PollardRho(x,c--);//当未分解成功时,换个c带入算法
	find(n/x,k);
	find(x,k);
	//递归操作
}

int main() {
    
    
	ios::sync_with_stdio(false);
	cin.tie(0);
	find(100000, 1554445);
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45560445/article/details/121589343