• BZOJ 4802: 欧拉函数 Pollard-Rho


    这个东西太好用了,感觉很多题都可以用这个东西来写暴力或乱搞. 

    #include <set> 
    #include <cmath> 
    #include <ctime>   
    #include <cstdio>   
    #include <algorithm>  
    #define ll long long 
    #define ull unsigned long long 
    #define setIO(s) freopen(s".in", "r" , stdin) 
    using namespace std;     
    set<ll>S;   
    set<ll>::iterator it;  
    int array[20]={2,3,5,7,11,13,17,19}; 
    ll mult(ll x,ll y,ll mod) 
    {
    	ll tmp=(long double)x/mod*y;    
    	return ((ull)x*y-(ull)tmp*mod+mod)%mod;      
    }
    ll F(ll a,ll c,ll mod) 
    { 
    	return (mult(a,a,mod)+c)%mod;   
    }
    ll qpow(ll base,ll k,ll mod) 
    {
    	ll tmp=1; 
    	for(;k;k>>=1,base=mult(base,base,mod)) if(k&1) tmp=mult(tmp,base,mod); 
    	return tmp;  
    } 
    int isprime(ll x) 
    { 
    	if(x<=1) return 1;   
    	int k,i,j;                      
    	ll cur=x-1,a,pre;                    
    	for(k=0;cur%2==0;cur>>=1) ++k;                 
    	for(i=0;i<8;++i) 
    	{
    		if(array[i]==x) return 1;               
    		a=pre=qpow(array[i],cur,x);       
    		for(j=1;j<=k;++j) 
    		{
    			a=mult(pre,pre,x); 
    			if(a==1&&pre!=1&&pre!=x-1) return 0; 
    			pre=a; 
    		}
    		if(a!=1) return 0; 
    	} 
    	return 1;   
    }
    ll pollard_rho(ll x) 
    {   
    	int k,step; 
    	ll s=0,t=0,c=rand()%(x-1)+1,val=1,d; 
    	for(k=1;;k<<=1,s=t,val=1) 
    	{ 
    		for(step=1;step<=k;++step) 
    		{
    			t=F(t,c,x);     
    			val=mult(val,abs(t-s),x); 
    			if(step%127==0) 
    			{
    				d=__gcd(val,x);  
    				if(d>1) return d;  
    			}
    		} 
    		d=__gcd(val,x); 
    		if(d>1) return d; 
    	}   
    }   
    void solve(ll x) 
    { 
    	if(x<2) return; 
    	if(isprime(x)) 
    	{
    		S.insert(x); 
    		return;  
    	} 
    	ll p=x; 
    	for(;p>=x;) p=pollard_rho(x);     
    	for(;x%p==0;) x/=p;   
    	solve(x),solve(p);   
    }
    int main() 
    { 
    	// setIO("input"); 
    	ll n,ans=1; 
    	scanf("%lld",&n),solve(n);   
    	for(it=S.begin();it!=S.end();it++) 
    	{ 
    		ll cur=(*it);     
    		for(;n%cur==0;) n/=cur,ans*=cur;    
    		ans=ans/cur*(cur-1);  
    	}
    	printf("%lld
    ",ans);   
    	return 0; 
    }
    

      

  • 相关阅读:
    浅谈js 构造函数 以及 new 运算符
    zabbix学习(一)——LNMP环境搭建及zabbix安装
    K8s部署使用CFSSL创建证书
    kubernetes环境搭建 -k8s笔记(一)
    windows下python3和python2虚拟环境配置
    QEMU/KVM网络模式(二)——NAT
    KVM安装
    QEMU网络模式(一)——bridge
    百度地图、腾讯地图、高德地图经纬度转换
    DOS入门(2)
  • 原文地址:https://www.cnblogs.com/guangheli/p/11506912.html
Copyright © 2020-2023  润新知