zoukankan      html  css  js  c++  java
  • POJ 2447

    挺水的一题。其实只要理解了RSA算法,就知道要使用大整数分解的方法来直接模拟了。

    不过,要注意两个INT64的数相乘来超范围

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <stdlib.h>
    #include <time.h>
    #define LL __int64 
    using namespace std;
    
    LL e,n,c,p,q,f;
    int cnt;
    LL prime[10];
    
    LL gcd(LL a,LL b){
    	if(b==0) return a;
    	return gcd(b,a%b);
    }
    
    LL random(LL nc){
    	return (LL)((double)rand()/RAND_MAX*nc+0.5);
    }
    
    LL multi(LL a,LL b,LL m){
    	LL ret=0;
    	while(b>0){
    		if(b&1)
    		ret=(ret+a)%m;
    		b>>=1;
    		a=(a<<1)%m;
    	}
    	return ret;
    }
    
    LL quick(LL a,LL b,LL m){
    	LL ans=1;
    	a%=m;
    	while(b){
    		if(b&1)
    		ans=multi(ans,a,m);
    		b>>=1;
    		a=multi(a,a,m);
    	}
    	return ans;
    }
    
    LL witness(LL a, LL nc){
    	LL m=nc-1;
    	int j=0;
    	while(!(m&1)){
    		j++;
    		m>>=1;
    	}
    	LL x=quick(a,m,nc);
    	if(x==1||x==nc-1)
    	return false;
    	while(j--){
    		x=multi(x,x,nc);
    		if(x==nc-1)
    		return false;
    	}
    	return true;
    }
    
    bool miller_rabin(LL nc){
    	if(nc<2) return false;
    	if(nc==2) return true;
    	if(!(nc&1)) return false;
    	for(int i=1;i<=10;i++){
    		LL a=random(nc-2)+1;
    		if(witness(a,nc)) return false;
    	}
    	return true;
    }
    
    LL pollard_rho(LL nc,int inc){
    	LL x,y,d,i=1,k=2;
    	x=random(nc-1)+1;
    	y=x;
    	while(1){
    		i++;
    		x=(multi(x,x,nc)+inc)%nc;
    		d=gcd(y-x,nc);
    		if(d>1&&d<nc)
    		return d;
    		if(y==x)
    		return nc;
    		if(i==k){
    			y=x;
    			k=(k<<1);
    		}
    	}
    }
    
    bool  find(LL nc,int k){
    	if(nc==1)
    	return false;
    	if(miller_rabin(nc)){
    		p=nc;
    		return true;
    	}
    	LL pe=nc;
    	while(pe>=nc)
    	pe=pollard_rho(pe,k--);
    	if(find(pe,k)) return true;;
    	if(find(nc/pe,k)) return true;;
    }
    
    void exgcd(LL a,LL b,LL &x,LL &y){
    	if(b==0){
    		x=1; y=0;
    		return ;
    	}
    	exgcd(b,a%b,x,y);
    	LL tmp=x;
    	x=y;
    	y=tmp-a/b*y;
    }
    
    int main(){
    	LL x,y;
    	while(scanf("%I64d%I64d%I64d",&c,&e,&n)!=EOF){
    		srand(time(0));
    		cnt=0;
    		find(n,201);
    		q=n/p;
    		f=(p-1)*(q-1);
    		exgcd(e,f,x,y);
    		x=(x%f+f)%f;
    		LL ans=quick(c,x,n);
    		printf("%I64d
    ",ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    [LeetCode#114]Flatten Binary Tree to Linked List
    [LeetCode#103]Binary Tree Zigzag Level Order Traversal
    [LeetCode#102]Binary Tree Level Order Traversal
    [LeetCode#145]Binary Tree Postorder Traversal
    [LeetCode#]Binary Tree Preorder Traversal
    [LeetCode#144]Binary Tree Preorder Traversal
    [LeetCode#94]Binary Tree Inorder Traversal
    [LeetCode#101]Symmetric Tree
    [LeetCode#100]Same Tree
    [LeetCode#104, 111]Maximum Depth of Binary Tree, Minimum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/3978196.html
Copyright © 2011-2022 走看看