UVALive 4998 Simple Encryption --DFS

题意: 给出K1,求一个12位数(不含前导0)K2,使得K1^K2 mod (10^12) = K2.

解法: 求不动点问题。

有一个性质: 如果12位数K2满足如上式子的话,那么K2%1,K2%10,K2%100,...,K2%10^12都会满足如上式子。那么我们可以dfs从后往前一个一个找出这个数的每一位。

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <cmath>

#include <algorithm>

#define SMod 1000000000000

#define ll long long

using namespace std;

#define N 10007



ll K1,K2;

long long mul(long long a,long long b,long long mod) {

    ll ite = (1LL<<20)-1;

    return (a*(b>>20)%mod*(1ll<<20)%mod+a*(b&(ite))%mod)%mod;

}



ll fastm(ll a,ll b,ll m) {

    ll res = 1LL;

    while(b) {

        if(b&1LL) res = mul(res,a,m);

        a = mul(a,a,m);

        b >>= 1;

    }

    return res;

}



ll wei[16],ans;



bool dfs(int c,ll now) {

    if(c == 13) {

        if(now >= wei[12]) { ans = now; return true; }

        return false;

    }

    ll W = wei[c];

    for(ll i=0;i<=9;i++) {

        ll tmp = W*i+now;

        if(fastm(K1,tmp,W) != tmp%W) continue;

        if(dfs(c+1,tmp)) return true;

    }

    return false;

}



int main()

{

    int t,cs = 1;

    wei[0] = 1LL;

    for(int i=1;i<=13;i++) wei[i] = wei[i-1]*10LL;

    while(scanf("%lld",&K1)!=EOF && K1) {

        dfs(0,0);

        printf("Case %d: Public Key = %lld Private Key = %lld\n",cs++,K1,ans%SMod);

    }

    return 0;

}
View Code

还有一种循环迭代的方法,随机选取一个超过10^12的数,如1000000000007,将其代入计算,如果f(x)!=x,那么令x=f(x),如此循环,能在短时间内找出合法解。不知道为啥。。

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <cmath>

#include <algorithm>

#define SMod 1000000000000

#define ll long long

using namespace std;



ll K1,K2;

long long mul(long long a,long long b,long long mod) {

    ll ite = (1LL<<20)-1;

    return (a*(b>>20)%mod*(1ll<<20)%mod+a*(b&(ite))%mod)%mod;

}



ll fastm(ll a,ll b,ll m) {

    ll res = 1LL;

    while(b) {

        if(b&1LL) res = mul(res,a,m);

        a = mul(a,a,m);

        b >>= 1;

    }

    return res;

}

ll f(ll x) {

    return fastm(K1,x,SMod);

}

ll gao(ll x) {

    while(1) {

        ll fx = f(x);

        if(fx == x) return x;

        x = fx;

    }

}



int main()

{

    int t,cs = 1;

    while(scanf("%lld",&K1)!=EOF && K1) {

        printf("Case %d: Public Key = %lld Private Key = %lld\n",cs++,K1,gao(1000000000007));

    }

}
View Code

 

你可能感兴趣的:(encrypt)