思路来源
K Upside down primes German Collegiate Programming Contest 2015 [ Miller_Rabin ]-CSDN博客
https://www.cnblogs.com/mrclr/p/10259874.html
Miller-Rabin
如果WA,可以在不TLE情况下,适当加T的次数
还有个O(1)的快速乘的方法
ll mul(ll u,ll v,ll p)
{
return (u*v-ll((long double)u*v/p)*p+p)%p;
}
#include <stdio.h>
#include <iostream>
using namespace std;
typedef long long ll;
const int T = 9;
ll mod_mult(ll a, ll b, ll mod) { //大数乘法取模
a %= mod;
b %= mod;
ll ans = 0;
while (b) {
if (b & 1) {
ans += a;
if (ans >= mod)
ans -= mod;
}
a <<= 1;
if (a >= mod) a = a - mod;
b >>= 1;
}
return ans;
}
ll mod_pow(ll x, ll n, ll mod) { //快速幂
if (n == 0) return 1;
ll res = mod_pow(mod_mult(x , x , mod), n / 2, mod);
if (n & 1) res = mod_mult(res , x , mod);
return res;
}
bool check(ll a, ll n, ll x, ll t) { //来判断是不是素数
ll ret = mod_pow(a, x, n), last = ret;
for (int i = 1; i <= t; i ++) {
ret = mod_mult(ret, ret, n);
if (ret == 1 && last != 1 && last != n - 1) return true;//合数
last = ret;
}
if (ret != 1) return true;
else return false;
}
bool Miller_Rabin(ll n) //Miller_Rabin算法
{
if( n < 2) return false;
if( n == 2) return true;
if(!(n & 1)) return false;//偶数
ll x = n - 1, t = 0;
while (!(x & 1)) { x >>= 1; t++;}
for (int i = 0; i < T; i ++) {
ll a = rand() % (n - 1) + 1;
if (check(a, n, x, t))
return false;
}
return true;
}
Pollard-pho
2023.10.7 板子替换为洛谷板子,可通过【模板】Pollard-Rho - 洛谷
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
typedef __int128 LL;
typedef double db;
inline ll read(){
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch)) {ans = (ans << 1) + (ans << 3) + ch - '0'; ch = getchar();}
if(last == '-') ans = -ans;
return ans;
}
ll ksm(ll a,ll b,ll mod) {
ll ans=1;
for(;b;a=(LL)a*a%mod,b/=2) {
if(b&1) ans=(LL)ans*a%mod;
}
return ans;
}
inline ll mul(ll x,ll y,ll Mod){
ll r=x*y-Mod*(ll)(1.L/Mod*x*y);
return r-Mod*(r>=Mod)+Mod*(r<0);
}
namespace MR{
const ll pr[7]={2,325,9375,28178,450775,9780504,1795265022};
inline bool isprime(ll x){
if(x<3||x%2==0)return x==2;
int r=0;
ll k=x-1;
for(;!(k&1);k>>=1,++r);
for(int T=7,j;T--;){
ll p=pr[T];
if(p%x==0)continue;
ll v=ksm(p,k,x);
if(v==1)continue;
for(j=1;j<=r;++j,v=mul(v,v,x))
if(v==x-1)break;
if(j>r)return 0;
}
return 1;
}
}
namespace PR{
vector<ll>ans;
inline ll calc(ll n){
if(!(n&1))return 2;
ll x=0,y=0,z=0,p=1,q,g;
for(int i=0;(i&255)||(g=__gcd(p,n))==1;\
++i,x=mul(x,x,n)+1,y=mul(y,y,n)+1,y=mul(y,y,n)+1){
if(x==y)x=z++,y=mul(x,x,n)+1;
q=mul(p,x-y+n,n);
if(q)p=q;
}
return g;
}
inline void split(ll n){
if(n==1)return;
if(MR::isprime(n)){
ans.push_back(n);
return;
}
ll d=calc(n);
while(d==1||d==n)d=calc(n);
split(d),split(n/d);
}
}
using namespace MR;
using namespace PR;
int main(){
//freopen("poll.out","w",stdout);
srand(time(0));
int T = read();
while(T--){
ll n = read();
ans.clear();
split(n);
int sz=ans.size();
if(sz==1)puts("Prime");
else printf("%lld\n",*max_element(ans.begin(),ans.end()));
}
return 0;
}