版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/86495669
题目p2107
From Tyvj Guest☆bzoj3667 Rabin-Miller算法
背景 Background
此系列问题为数论专题
具体参考博文
http://blog.csdn.net/chty2018/article/details/53432272
描述 Description
给定一个CAS,以下CAS行,每行一个数字,保证在64位长整形范围内,并且没有负数。
你需要对于每个数字:
第一,检验是否是质数,是质数就输出Prime
第二,如果不是质数,输出它最大的质因子是哪个。
输入格式 Input Format
第一行CAS(CAS<=350,代表测试数据的组数)
以下CAS行:每行一个数字,保证是在64位长整形范围内的正数。
输出格式 Output Format
对于每组测试数据:输出Prime,代表它是质数,或者输出它最大的质因子,代表它是和数
样例输入 Sample Input
6
2
13
134
8897
1234567654321
1000000000000
样例输出 Sample Output
6
2
13
134
8897
1234567654321
1000000000000
时间限制 Time Limitation
1s
注释 Hint
1s
来源 Source
题面,数据来自宋逸群
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll a[]={2,3,5,7,11,13,17,19,23,29};
char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
x=0;
static ll f=1;
static char ch=getc();
while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getc(); }
while (ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48), ch=getc();
x*=f;
}
template<typename T>inline void write(T x)
{
if (x<0) x=-x,putchar('-');
if (x>9) write(x/10);
putchar(x%10+'0');
}
inline ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
inline ll mul(ll a,ll b,ll p)
{
ll tmp=(a*b-(ll)((long double)a/p*b+1e-8)*p);
return tmp<0?tmp+p:tmp;
}
inline ll power(ll a,ll b,ll p)
{
ll ans=1;
a%=p;
while (b)
{
if (b&1)
ans=mul(ans,a,p);
a=mul(a,a,p);
b>>=1;
}
return ans;
}
inline bool check(ll a,ll n,ll r,ll s)
{
ll ans=power(a,r,n),p=ans;
for (register int i=1;i<=s;++i)
{
ans=mul(ans,ans,n);
if (ans==1 && p!=1 && p!=n-1) return 1;
p=ans;
}
if (ans!=1) return 1;
return 0;
}
inline bool RabinMiller(ll n)
{
if (n<=1) return 0;
if (n==2) return 1;
if (n%2==0) return 0;
ll r=n-1,s=0;
while (r%2==0)
r>>=1,++s;
for (register int i=0;i<10;++i)
if (check(rand()%(n-1)+1,n,r,s))
return 0;
return 1;
}
inline ll PollardRho(ll n,ll c)
{
ll k=2,x=rand()%n,y=x,p=1;
for (register ll i=1;p==1;++i)
{
x=(mul(x,x,n)+c)%n;
p=gcd(n,abs(x-y));
if (i==k) y=x,k<<=1;
}
return p;
}
ll mx;
inline void find(ll n)
{
if (n==1) return ;
if (RabinMiller(n))
{
mx=max(mx,n);
return ;
}
ll t=n;
while (t==n)
t=PollardRho(n,rand()%(n-1)+1);
find(t),find(n/t);
}
int main()
{
ll t;read(t);
while (t--)
{
ll x;read(x);
mx=0;
find(x);
if (mx==x)
puts("Prime");
else
write(mx),putchar('\n');
}
return 0;
}
这是个很正经的代码。。。。。。。然而最后一个点T。。。。。。。。。。。
然后发现评论区出现了位大佬,他的代码。。。。。。。。。。。。。。。反正A了。。。。而且跑的飞快。。。。。。。。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = (1 << 7) - 1;
const int pr[12] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
//平台无关式longlong乘法取模
ll mmul(ll a, ll b, ll m)
{
ll d = ((long double)a / m * b + 1e-8);
ll r = a * b - d * m;
return r < 0 ? r + m : r;
}
ll mpow(ll a, ll b, ll m)
{
ll r = 1;
for (; b; b >>= 1, a = mmul(a, a, m))
if (b & 1) r = mmul(r, a, m);
return r;
}
//玄学位运算版gcd
ll gcd(ll a, ll b)
{
if (!a) return b;
if (!b) return a;
#define ctz __builtin_ctzll
int t = ctz(a | b);
a >>= ctz(a);
do
{
b >>= ctz(b);
if (a > b)
{
ll t = b;
b = a;
a = t;
}
b -= a;
} while (b != 0);
return a << t;
}
int prime(ll n)
{
if (n == 1) return 0;
if (n == 2 || n == 3 || n == 5) return 1;
//瞬间排除掉73.33%的数 O_O
if (!(n & 1) || (n % 3 == 0) || (n % 5 == 0)) return 0;
ll m = n - 1;
int k = 0;
while (!(m & 1)) m >>= 1, k++;
for (int ip = 0; ip < 12 && pr[ip] < n; ++ip)
{
ll x = mpow(pr[ip], m, n), y = x;
for (int i = 0; i < k; ++i)
{
x = mmul(x, x, n);
if (x == 1 && y != 1 && y != n - 1) return 0;
y = x;
}
if (x != 1) return 0;
}
return 1;
}
inline ll g(ll x, ll n, ll a)
{
ll t = mmul(x, x, n) + a;
return t < n ? t : t - n;
}
ll rho(ll n)
{
//又来特判了。。。
if (n % 2 == 0) return 2;
if (n % 3 == 0) return 3;
ll x = 0, y = x, t = 1, q = 1, a = (rand() % (n - 1)) + 1;
for (int k = 2;; k <<= 1, y = x, q = 1)
{
for (int i = 1; i <= k; ++i)
{
x = g(x, n, a);
q = mmul(q, abs(x - y), n);
if (!(i & M))
{
t = gcd(q, n);
if (t > 1) break;
}
}
if (t > 1 || (t = gcd(q, n)) > 1) break;
}
if (t == n)
{
t = 1;
while (t == 1)
t = gcd(abs((x = g(x, n, a)) - y), n);
}
return t;
}
ll f[105];
int tot;
void work(ll n)
{
if (n == 1) return;
if (prime(n))
{
f[tot++] = n;
return;
}
ll t = n;
while (t == n) t = rho(n);
work(t);
work(n / t);
}
int main()
{
srand(19260817);
int t;ll n;
cin >> t;
while (t--)
{
cin >> n;
tot = 0;
work(n);
sort(f, f + tot);
if (tot == 1)
cout << "Prime" << endl;
else
cout << f[tot - 1] << endl;
}
return 0;
}
对此,我。。。。。。只能无语。