zoukankan      html  css  js  c++  java
  • POJ 1811

    使用Pollard_rho算法就可以过了

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <stdlib.h>
    #include <time.h>
    #define LL __int64
    using namespace std;
    LL ans;
    const LL C=201;
    LL random(LL n){
    	return (LL)((double)rand()/RAND_MAX*n+0.5);
    }
    
    LL gcd(LL a,LL b){
    	if(b==0) return a;
    	return gcd(b,a%b);
    }
    
    LL multi(LL a,LL b,LL m){  a*b%m这个函数写得真心好,很好地避免了超出范围的情    况
    	LL ret=0;
    	while(b>0){
    		if(b&1)
    		ret=(ret+a)%m;
    		b>>=1;
    		a=(a<<1)%m;
    	}
    	return ret;
    }
    
    LL Pollard_rho(LL n, LL c){
    	LL x,y,d,i=1,k=2;
    	x=random(n-1)+1;
    	y=x;
    	while(true){
    		i++;
    		x=(multi(x,x,n)+c)%n;
    		d=gcd(y-x,n);
    		if(d>1&&d<n) return d;
    		if(y==x) return n;
    		if(i==k){
    			y=x;
    			k=k<<1;
    		}
    	}
    }
    
    LL quick(LL a,LL k,LL m){
    	LL ans=1;
    	a%=m;
    	while(k){
    		if(k&1){
    			ans=multi(ans,a,m);
    		}
    		k=k>>1;
    		a=multi(a,a,m);   // 这里如果不写函数直接乘会超范围
    	}
    	return ans;
    }
    
    bool Witness(LL a, LL n){
    	LL m=n-1;
    	int j=0;
    	while(!(m&1)){
    		j++;
    		m=m>>1;
    	}
    	LL x= quick(a,m,n);
    	if(x==1||x==n-1)
    	return false;
    	while(j--){
    		x=multi(x,x,n);
    		if(x==n-1)
    		return false;
    	}
    	return true;
    }
    
    bool Miller_Rabin(LL n){
    	if(n<2) return false;
    	if(n==2) return true;
    	if(!(n&1)) return false;
    	for(int i=1;i<=10;i++){
    		LL a=random(n-2)+1;
    		if(Witness(a,n)) return false;
    	}
    	return true;
    }
    
    void find(LL n){
    	if(n==1) return ;
    	if(Miller_Rabin(n)){
    		if(n<ans)
    		ans=n;
    		return ;
    	}
    	LL p=n;
    	while(p>=n)
    	p=Pollard_rho(p,random(n-2)+1);
    	find(p);
    	find(n/p);
    }
    
    int main(){
    	LL n; int T;
    	srand(time(0));
    	scanf("%d",&T);
    	while(T--){
    		scanf("%I64d",&n);
    		if(Miller_Rabin(n)){
    			printf("Prime
    ");
    			continue;
    		}
    		ans=(1LL<<60);
    		find(n);
    		printf("%I64d
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    推销
    5132. 颜色交替的最短路径
    5130. 等价多米诺骨牌对的数量
    @babel/plugin-transform-runtime和@babel/preset-env的区别
    5128. 最深叶节点的最近公共祖先(二叉树)
    1094. 拼车
    1109. 航班预订统计(数组)
    5129. 表现良好的最长时间段(数组)
    path.resove 和 path.join
    【原生】 call、apply、bind 的基本使用方法,已经解析了某些源码
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/3961662.html
Copyright © 2011-2022 走看看