zoukankan      html  css  js  c++  java
  • BZOJ4802 欧拉函数 数论

    原文链接http://www.cnblogs.com/zhouzhendong/p/8117744.html


    题目传送门 - BZOJ4802


    题意概括

    Description

    已知N,求phi(N)

    Input

    正整数N。N<=10^18

    题解

      Miller_Rabin+Pollard_Rho

      至于Pollard_Rho,我感到很奇怪。判定的时候为何不能丢第一个值!!

      请看下面两个代码,第一个对的,第二个错的……


    代码

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    #include <ctime>
    using namespace std;
    typedef long long LL;
    LL gcd(LL a,LL b){
    	return b?gcd(b,a%b):a;
    }
    LL Mul(LL a,LL b,LL mod){
    	LL ans=0;
    	a%=mod;
    	while (b){
    		if (b&1)
    			ans=(ans+a)%mod;
    		b>>=1,a=(a<<1)%mod;
    	}
    	return ans;
    }
    LL Pow(LL a,LL b,LL mod){
    	LL ans=1;
    	a%=mod;
    	while (b){
    		if (b&1)
    			ans=Mul(ans,a,mod);
    		b>>=1,a=Mul(a,a,mod);
    	}
    	return ans;
    }
    bool Miller_Rabin(LL n){
    	if (n==2)
    		return 1;
    	if (n<2||n%2==0)
    		return 0;
    	LL m=n-1,k=0;
    	while (!(m&1))
    		m>>=1,k++;
    	for (int i=0;i<10;i++){
    		LL a=rand()%(n-1)+1,x=Pow(a,m,n),y;
    		for (int j=0;j<k;j++){
    			y=Mul(x,x,n);
    			if (y==1&&x!=1&&x!=n-1)
    				return 0;
    			x=y;
    		}
    		if (x!=1)
    			return 0;
    	}
    	return 1;
    }
    LL rnd(LL x,LL n,LL c){
    	return (Mul(x,x,n)+c)%n;
    }
    LL Pollard_Rho(LL n,LL c){
    	LL x,y;
    	while (1){
    		x=rand()%(n-1)+1,y=rnd(x,n,c);
    		while (1){
    			if (x==y)
    				break;
    			LL d=gcd(llabs(y-x)%n,n);
    			if (1<d&&d<n)
    				return d;
    			x=rnd(x,n,c);
    			y=rnd(rnd(y,n,c),n,c);
    		}
    		c=rand()%n;
    	}
    }
    LL n,x[66],pcnt;
    void find(LL n){
    	if (n==1)
    		return;
    	if (Miller_Rabin(n)){
    		x[++pcnt]=n;
    		return;
    	}
    	LL p=Pollard_Rho(n,rand()%n);
    	find(p);
    	find(n/p);
    }
    int main(){
    	srand(19260817);
    	scanf("%lld",&n);
    	pcnt=0;
    	find(n);
    	sort(x+1,x+pcnt+1);
    	LL yz=pcnt?x[1]-1:1;
    	for (int i=2;i<=pcnt;i++)
    		yz=yz*(x[i]-(bool)(x[i]!=x[i-1]));
    	printf("%lld
    ",yz);
    	return 0;
    }
    

      

  • 相关阅读:
    php中的form表单
    http
    PHP做的简单计算器
    用Js写贪吃蛇
    ajax简单操作,验证用户名是否可以
    关于ARM PC值
    阅读脚本控制pwm代码
    编译选项
    关于机器码、原码、反码、补码
    makefile学习之函数
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ4802.html
Copyright © 2011-2022 走看看