素数判定——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;
}