BZOJ_4802_欧拉函数_MR+pollard rho+欧拉函数
BZOJ_4802_欧拉函数_MR+pollard rho+欧拉函数
Description
已知N,求phi(N)
Input
正整数N。N<=10^18
Output
输出phi(N)
Sample Input
8
Sample Output
4
直接MR+Pollard rho分解质因数即可。具体可见https://www.cnblogs.com/suika/p/9127065.html
记得判重,我的map不知道为何T了。
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <cmath> #include <map> using namespace std; typedef long long ll; typedef double f2; map<ll,int>mp; ll ch(ll x,ll y,ll mod) {ll re=0;for(;y;y>>=1ll,x=(x+x)%mod) if(y&1ll) re=(re+x)%mod; return re;} ll random(ll x,ll y) {return ((rand()*(1ll<<45))+(rand()*(1ll<<30))+(rand()<<15)+(rand()))%(y-x+1)+x;} ll qp(ll x,ll y,ll mod) {ll re=1;for(;y;y>>=1ll,x=ch(x,x,mod)) if(y&1ll) re=ch(re,x,mod); return re;} ll a[]={2,3,5,7,11,13,17,19,23,29}; ll ans; ll Abs(ll x) {return x>0?x:-x;} ll gcd(ll x,ll y) {return y?gcd(y,x%y):x;} ll b[250000]; bool check(ll a,ll n,ll r,ll s) { ll x=qp(a,r,n),y=x,i; for(i=1;i<=s;i++,y=x) {x=ch(x,x,n); if(x==1&&y!=1&&y!=n-1) return 0;} return x==1; } bool MR(ll n) { if(n<=1) return 0; ll r=n-1,s=0,i; for(;!(r&1);r>>=1ll,s++); for(i=0;i<=9;i++) { if(a[i]==n) return 1; if(!check(a[i],n,r,s)) return 0; } return 1; } ll f(ll x,ll c,ll mod) {return (ch(x,x,mod)+c)%mod;} ll PR(ll n,ll c) { ll x=random(0,n-1),y=f(x,c,n),p; for(p=1;p==1&&x!=y;) { x=f(x,c,n); y=f(f(y,c,n),c,n); p=gcd(Abs(x-y),n); } return p==1?n:p; /*ll k=2,x=rand()%n,y=x,p=1,i; for(i=1;p==1;i++) { printf("%lld %lld\n",x,y); x=f(x,c,n); p=gcd(n,Abs(x-y)); if(i==k) y=x,k+=k; } return p;*/ } void solve(ll n) { if(n==1) return ; if(MR(n)) { b[++b[0]]=n; return ; } ll t=n; while(t==n) t=PR(n,rand()%n); solve(t); solve(n/t); } int main() { ll n; srand(19260817); scanf("%lld",&n); ans=n; int i; for(i=0;i<=9;i++) { if(n%a[i]==0) { ans=ans/a[i]*(a[i]-1); while(n%a[i]==0) n/=a[i]; } } solve(n); int tot=unique(b+1,b+b[0]+1)-b-1; for(i=1;i<=tot;i++) ans=ans/b[i]*(b[i]-1); printf("%lld\n",ans); }