原本是想把这个算法搞懂的,然后在网上看了又看,觉得,还是有时间再来看吧,我错了。
看到了一个大佬的博客,顺带收集一下板子
这个板子可以求大数的最大的因子。
#define LL long long
bool IsPrime(LL);//返回素性测试结果
LL GCD(LL,LL);//返回两个数的GCD
LL Mix(LL,LL,LL);//返回两个数在模运算下的乘积void MaxFactor(LL n,LL &ans)
{if(n==1||n<=ans||IsPrime(n)){return;//判断特殊情况:n为1或素数}for(LL c=rand()%(n-1)+1;;c++){//为防止随机数无效化,使用死循环LL t1=rand()%(n-1)+1,t2=(Mix(t1,t1,n)+c)%n;LL p=1,i=0,g=0;while(t1!=t2){p=Mix(p,abs(t1-t2),n);if(!p){//乘积为0时说明找到了一个因子g=GCD(n,abs(t1-t2));if(g>1&&g<n){MaxFactor(g,ans);MaxFactor(n/g,ans);}return;}++i;if(i==127){//当有127个数时强制测试g=GCD(n,p);if(g>1&&g<n){MaxFactor(g,ans);MaxFactor(n/g,ans);return;}p=1,i=0;}t1=(Mix(t1,t1,n)+c)%n;t2=(Mix(t2,t2,n)+c)%n;t2=(Mix(t2,t2,n)+c)%n;}g=GCD(n,p);if(g>1&&g<n){//循环退出后收尾MaxFactor(g,ans);MaxFactor(n/g,ans);return;}}
}
又找了一个板子,这个好像可以求出所有的因子(保存在数组factor中)
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<stdlib.h>
#include<time.h>
#define times 20
using namespace std;
#define ll long long
ll total;
ll factor[110];
ll qmul(ll a,ll b,ll M){a%=M;b%=M;ll ans=0;while (b){if (b&1){ans=(ans+a)%M;}a=(a<<=1)%M;b>>=1;}return ans%M;
}///快乘,因为两个longlong的数相乘可能会溢出,所以这里转乘法为加法,思想和快速幂相似
ll qpow(ll a,ll b,ll int M){ll ans=1;ll k=a;while(b){if(b&1)ans=qmul(ans,k,M)%M;k=qmul(k,k,M)%M;b>>=1;}return ans%M;
}
bool witness(ll a,ll n,ll x,ll sum){ll judge=qpow(a,x,n);if (judge==n-1||judge==1)return 1;while (sum--){judge=qmul(judge,judge,n);if (judge==n-1)return 1;}return 0;
}
bool miller(ll n){ ///判断素数if (n<2)return 0;if (n==2)return 1;if ((n&1)==0)return 0;ll x=n-1;ll sum=0;while (x%2==0){x>>=1;sum++;}for (ll i=1;i<=times;i++){ll a=rand()%(n-1)+1;if (!witness(a,n,x,sum))return 0; ///费马小定理的随机数检验}return 1;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);
}
ll pollard(ll n,ll c){ll x,y,d,i=1,k=2;x=rand()%n;y=x;while (1){i++;x=(qmul(x,x,n)+c)%n; ///不断调整xd=gcd(y-x,n);if (d<0)d=-d;if (d>1&&d<n)return d; ///找到因子if (y==x)return n; ///找到循环,返回n,重新来if (i==k){ ///一个优化y=x;k<<=1;}}
}
void find(ll n){///寻找这个数的素因子,并存起来if (miller(n)){factor[++total]=n;return ;}ll p=n;while (p>=n) p=pollard(p,rand()%(n-1)+1); ///不断找因子,知道找到为止,返回n说明没找到find(n/p);find(p);
}
int main(){ll n,m,i,t;scanf("%lld",&t);while (t--){scanf("%lld",&n);if (miller(n)) printf("Prime\n");else {memset(factor,0,sizeof(factor));total=0;find(n);sort(factor+1,factor+total+1);printf("%lld\n",factor[1]);}}
}