UVALive 4998 Simple Encryption

时间:2023-03-09 14:35:31
UVALive 4998	Simple Encryption

题目描述:

  输入正整数K1(K1<=5000),找一个12位正整数K2使得K1K2=K2(mod 1012)。

解题思路:

  压缩映射原理:设X是一个完备的度量空间,映射ƒ:Χ→Χ 把每两点的距离至少压缩λ倍,即d(ƒ(x),ƒ(y))≤λd(x,y),这里λ是一个小于1的常数,那么ƒ必有而且只有一个不动点,而且从Χ的任何点x0出发作出序列x1=ƒ(x0),x2=ƒ(x1),...,xn=ƒ(x(n-1)),...,这序列一定收敛到那个不动点。

  题目要求解的方程形式是f(K2)=K2,很直接地就想到不动点原理。

  另外,K2的值较大,在求解K1K2(mod 1012)时要利用矩阵快速幂,同时由于是对1012取模,两个1012级别的数相乘结果会爆long long,所以在做乘法时要用到O(1)快速乘。

代码如下:

#include<bits/stdc++.h>
using namespace std; typedef long long ll; const ll MOD=1e12; ll mul(ll a,ll b)
{
ll ite=(1ll<<)-;
return (a*(b>>)%MOD*(<<)%MOD+a*(b&ite)%MOD)%MOD;
} ll pow_mod(ll a,ll b)
{
ll ret=; while(b)
{
if(b&)
ret=mul(ret,a)%MOD; b>>=;
a=mul(a,a)%MOD;
}
return ret;
} ll solve(ll n)
{
ll x=1e12;
while()
{
ll ans=pow_mod(n,x);
if(ans==x)
return ans; x=ans;
}
} int main()
{
ll k1;
int Case=;
while(scanf("%lld",&k1)&&k1)
{
ll k2=solve(k1);
printf("Case %d: Public Key = %lld Private Key = %lld\n",++Case,k1,k2);
}
return ;
}