• UVA12253 简单加密法 Simple Encryption


    这题到现在还是只有我一个人过?太冷门了吧,毕竟你谷上很少有人会去做往年ACM比赛的题

    题面意思很简单,每次给出(K_1),让你求一个(K_2)满足(K_1^{K_2}equiv K_2(mod 10^{12}))

    题目乍一看很有数学风格,看到取模和幂次想到什么?

    费马大小定理,BSGS,二次探测,不过在这里好像都用不了啊。

    所以我们先考虑一个最朴素的想法:爆搜,每次直接枚举每一位上放什么数字,然后快速幂判断。

    这样肯定T飞啊,所以我们进行一个大力观察,我们手玩下第二个样例:

    [99^9equiv 9(mod 10^{1});99^9equiv 99(mod 10^{2}) ]

    [99^{99}equiv 99(mod 10^{2});99^{99}equiv 899(mod 10^{3}) ]

    [99^{899}equiv 899(mod 10^{3});99^{899}equiv 9899(mod 10^{4}) ]

    (dots)

    发现什么没,若(K_1^{n}equiv dn(mod 10^{operatorname{bit}_n+1})),那么(K_1^{dn}equiv dn(mod 10^{operatorname{bit}_{dn}}))!(上面的(dn)表示在(n)前面放一个(d)

    这个规律的提出在大刘的蓝书上也有涉及,并且可以用归纳法证明之,这里不再赘述。

    所以接下来的流程就出来了,我们对于每一位,如果可以用这个规律刷出下一位就直接跳,否则(就是用规律算出前导零的情况)再枚举这一位的取值。

    实际应用下在这个trick的优化下,再加上玄学的(O(1))快速乘,可以跑的非常快((200ms)过了(1600)组数据)。

    CODE

    #include<cstdio>
    #define RI register int
    typedef long long LL;
    const LL lim=1e11,R=(1LL<<20)-1; int n,cases;
    LL quick_mul(LL x, LL y, LL mod)
    {
        return (x *(y>>20)%mod*(1LL<<20)%mod+x*(y&(R))%mod)%mod;
    }
    inline LL quick_pow(LL x,LL p,LL mod,LL mul=1)
    {
        for (;p;p>>=1,x=quick_mul(x,x,mod)) if (p&1) mul=quick_mul(mul,x,mod); return mul;
    }
    inline bool expand(int idx,LL n,LL p,LL mod)
    {
        int t; LL nxt; while (idx<12) if ((nxt=quick_pow(n,p,10LL*mod))!=p) p=nxt,++idx,mod*=10LL; else break;
        if (idx==12&&quick_pow(n,p,mod)==p) return printf("%lld
    ",p),1; return 0;
    }
    inline bool DFS(int idx,LL p,LL mod)
    {
        if (idx==12) { if (p>=lim&&quick_pow(n,p,mod)==p) return printf("%lld
    ",p),1; return 0; }
        if (quick_pow(n,p,mod)==p&&expand(idx,n,p,mod)) return 1;
        for (RI i=0;i<10;++i) if (quick_pow(n,1LL*i*mod+p,mod)==p&&DFS(idx+1,1LL*i*mod+p,10LL*mod)) return 1; return 0;
    }
    int main()
    {
        //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
        while (scanf("%d",&n),n)
        {
            printf("Case %d: Public Key = %d Private Key = ",++cases,n);
            for (RI i=0;i<10;++i) if (DFS(1,i,10)) break;
        }
        return 0;
    }
    
  • 相关阅读:
    汇编指令
    汇编指令
    汇编指令
    字在寄存器中的存储
    汇编指令
    字在寄存器中的存储
    汇编指令
    8086CPU的8位寄存器数据存储情况
    [转载]使用嵌入式 Tomcat 简化程序调试
    [转载]Java语法总结
  • 原文地址:https://www.cnblogs.com/cjjsb/p/10289897.html
Copyright © 2020-2023  润新知