2018 China Collegiate Programming Contest Final (CCPC-Final 2018)-K

2018 China Collegiate Programming Contest Final (CCPC-Final 2018)-K - Mr. Panda and Kakin-中国剩余定理+同余定理


【Problem Description】

[求解x^{2^{30}+3}=cpmod n ]

其中(n=pcdot q)(p)为小于(x)的最大素数,(q)为大于(x)的最小素数,(x)([10^5,10^9])内随机选择的数。(0< c<n)

【Solution】

(a=2^{30}+3),所以有(x^a=cpmod nLeftrightarrow x^{a mod varphi(n)}=cpmod n)。又因为(n=pcdot q),所以有(x^{a mod (p-1)cdot (q-1)}=cpmod n),求出(a)在模((p-1)cdot (q-1))意义下的逆元(d),则(x=c^dpmod n)。然后用中国剩余定理求解答案(x)即可。

至于(p,q),由题意可知,(p,q)都在(sqrt{n})附近,所以暴力求解即可。


【Code】

#include<bits/stdc++.h>
using namespace std;
#define int long long
int exgcd(int a,int b,int &x,int &y){ //扩展欧几里得
	if(a==0&&b==0) return -1;
	if(b==0){
		x=1;y=0;
		return a;
	}
	int gcd=exgcd(b,a%b,y,x);
	y-=a/b*x;
	return gcd;
}
int solve(int a,int b,int c){ //求逆元
	int x,y;
	int gcd=exgcd(a,b,x,y);
	if(c%gcd!=0) return -1;
	return (x%b+b)%b;
}
int fpow(int a,int b,int mod){ //快速幂
	int ans=1;a%=mod;
	while(b){
		if(b&1) (ans*=a)%=mod;
		(a*=a)%=mod;
		b>>=1;
	}
	return ans;
}
int fmul(int a,int b,int mod){ //快速乘
	int ans=0;a%=mod;
	while(b){
		if(b&1) ans=(ans+a)%mod;
		a=(a+a)%mod;
		b>>=1;
	}
	return ans;
}
int crt(int ai[], int mi[], int len) { //中国剩余定理
    int ans = 0, lcm = 1;
    for (int i = 0; i < len; i++) lcm *= mi[i];
    for (int i = 0; i < len; i++) {
        int Mi = lcm / mi[i];
        int inv = fpow(Mi, mi[i] - 2, mi[i]);
        int x = fmul(fmul(inv, Mi, lcm), ai[i], lcm); //若lcm大于1e9需要用快速乘fmul
        ans = (ans + x) % lcm;
    }
    return ans;
}
int mi[5],ai[5];
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T,ca=0;cin>>T;
	while(T--){
		cout<<"Case "<<++ca<<": ";
		int n,c,p,q;cin>>n>>c;
		for(int i=sqrt(n);i>=0;i--) if(n%i==0){
			p=i;q=n/i;
			break;
		}
		int d=solve((1LL<<30)+3,(p-1)*(q-1),1);
		if(d==-1){
			cout<<"-1"<<endl;
			continue;
		}
		ai[0]=fpow(c,d,p);ai[1]=fpow(c,d,q);
		mi[0]=p;mi[1]=q;
		cout<<crt(ai,mi,2)<<endl;
	}
	return 0;
}

原文地址:https://www.cnblogs.com/--Simon/p/11725961.html