BZOJ 4802 rho素数分解
我re了很久,最后,我把随机种子从\(time(NULL)\) 改成了随便一个数,然后就A了
这。。。。

果然,信息学就是玄学。
其实就是\(miller-rabin\)和\(rho\)算法的板子。
\(rho\)算法大概也明白了一点。
\(miller-rabin\)发现还是挺容易写的。
然后这题最主要的是一些数论的编程细节。
首先
如果是乘法模运算,换成加法会很稳妥。
然后,如果你很懒,就不必把快速幂写成迭代实现,其实也很简单
当你纠结\(unsigned long long\) 怎么输入的时候,一个\(cin\)就可以救你于水火。
这个随机算法其实和确定算法相比误差极小,所以,不要怂的开1000次测试。实际上20次就够了。
/**************************************************************
Problem: 4802
User: rsq
Language: C++
Result: Accepted
Time:344 ms
Memory:1296 kb
****************************************************************/
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<vector>
#include<ctime>
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
typedef unsigned long long ULL;
ULL Mul(ULL a,ULL b,ULL p)
{
ULL res=0;
while(b)
{
if(b&1)res=(res+a)%p;
a=(a+a)%p;b>>=1;
}
return res;
}
ULL Pow(ULL a,ULL b,ULL Mod)
{
if(b == 0) return 1;
ULL ans = Pow(a,b/2,Mod);
ans = Mul(ans,ans,Mod);
if(b&1) ans = Mul(ans,a,Mod);
return ans;
}
bool check(ULL a,ULL r,ULL s,ULL Mod) //true为合数,false可能为素
{
ULL ans = Pow(a,r,Mod);
ULL p = ans;
for(ULL i = 0;i < s;i++){
ans = Mul(ans,ans,Mod);
if(ans == 1&&p != 1&&p != Mod-1) return true;
p = ans;
}
if(ans != 1) return true;
return false;
}
bool MR(ULL n)
{
if(n < 2) return false;
if(n == 2||n == 3|| n == 5) return true;
if(n%2 == 0) return false;
ULL r = n-1;ULL s = 0;
while(r%2 == 0) r/=2,s++;
for(int i = 0;i < 50;i++){
ULL a = (rand()%(n-2)) +1;
if(check(a,r,s,n)) return false;
}
return true;
}
ULL gcd(ULL a,ULL b)
{
if(b == 0) return a;
else return gcd(b,a%b);
}
vector<ULL> syz;
set<ULL> S;
ULL rho(ULL c,ULL n)
{
ULL k = 2,x = rand()%n,y = x,p = 1;
for(int i = 1;p == 1;i++){
x = (Mul(x,x,n)+c)%n;
p = y > x?y-x:x-y;
p = gcd(n,p);
if(i == k) y = x,k += k;
}
return p;
}
void solve(ULL n)
{
if(n < 2) return ;
ULL k = n;
if(MR(n)){
if(!S.count(n)){
syz.push_back(n);
S.insert(n);
}return;}
ULL t = n;
while(t == n) t = rho(rand()%(n-1)+1,n);
solve(t);
solve(n/t);
}
int main()
{
srand(233333);
ULL n;
cin>>n;
if(n == 0){printf("0\n");exit(0);}
ULL ans = n;
solve(n);
for(int i = 0;i < syz.size();i++)
ans = ans/syz[i]*(syz[i]-1);
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号