zoukankan      html  css  js  c++  java
  • password

    Description
    Rivest 是密码学专家。近日他正在研究一种数列E = {E[1],E[2],……,E[n]},
    且E[1] = E[2] = p(p 为一个质数),E[i] = E[i-2]*E[i-1] (若2<i<=n)。
    例如{2,2,4,8,32,256,8192,……}就是p = 2 的数列。在此基础上他又设计了一种加密算法,
    该算法可以通过一个密钥q (q < p)将一个正整数n 加密成另外一个正整数d,计算公式为:
    d = E[n] mod q。现在Rivest 想对一组数据进行加密,但他对程序设计不太感兴趣,请你帮
    助他设计一个数据加密程序。
    Input
    第一行读入m,p。其中m 表示数据个数,p 用来生成数列E。以下有m 行,每行有2 个
    整数n,q。n 为待加密数据,q 为密钥。数据范围: 0 < p n< 2^31 0 < q < p 0 < m <= 5000。
    Output
    将加密后的数据按顺序输出到文件第i 行输出第i 个加密后的数据。输入样例1 2 7 4 5 4
    6 输入样例2 4 7 2 4 7 1 6 5 9 3
    Sample Input
    输入样例1
    2 7
    4 5
    4 6
    输入样例2
    4 7
    2 4
    7 1
    6 5
    9 3
    Sample Output
    输出样例1
    31
    输出样例2
    3011

    solution

    计算公式为:d=E[n] mod q

                         d=p^(fibonaqi[n]) mod q

    所以 要 求斐波那契的第n项,但是我们发现long long也只能开到九十多项,想到了 降幂

    这里就用到了  欧拉定理: a^b%k = a^(b%φ(k)) % k                  gcd(a,k)==1

                                             a^b%k = a^(b%φ(k)+φ(k)) % k          gcd(a,k)!=1

    用这段神奇的code 来求 φ(k)

     1 ll oula(ll t)
     2 {
     3   ll kk=t;
     4   for(ll i=2;i*i<=t;++i)
     5   if(t%i==0)
     6   {
     7     kk=kk-kk/i;
     8     while(t%i==0)
     9       t/=i;
    10   }
    11   if(t>1)kk=kk-kk/t;
    12   return kk;
    13 }
    神奇的code

    再用矩阵快速幂 求指数的斐波那契

    最后快速幂即可      (注意要用long long)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #define ll long long
     5 #define mem(a,b) memset(a,b,sizeof(a))
     6 using namespace std;
     7 
     8 int m,p,n;
     9 ll q;
    10 ll f[6][6],a[6][6],temp[6][6];
    11 ll mod;
    12 
    13 ll oula(ll t)
    14 {
    15     ll kk=t;
    16     for(ll i=2;i*i<=t;++i)
    17       if(t%i==0)
    18       {
    19             kk=kk-kk/i;
    20             while(t%i==0)
    21               t/=i;
    22         }
    23     if(t>1)kk=kk-kk/t;
    24     return kk;
    25 }
    26 
    27 inline void chu()
    28 {
    29     mem(f,0);
    30     mem(a,0);
    31     f[1][1]=1;f[2][2]=1;
    32     a[1][1]=1;a[1][2]=1;a[2][1]=1;
    33 }
    34 
    35 inline ll cheng()
    36 {
    37     --n;
    38     while(n)
    39     {
    40         if(n&1)
    41         {
    42             for(int i=1;i<=2;++i)
    43               for(int j=1;j<=2;++j)
    44               {
    45                     temp[i][j]=0;
    46                     for(int k=1;k<=2;++k)
    47                       temp[i][j]=(temp[i][j]+f[i][k]*a[k][j]%mod)%mod;
    48                 }
    49             for(int i=1;i<=2;++i)
    50               for(int j=1;j<=2;++j)
    51                 f[i][j]=temp[i][j];
    52         }
    53         for(int i=1;i<=2;++i)
    54           for(int j=1;j<=2;++j)
    55           {
    56                 temp[i][j]=0;
    57                 for(int k=1;k<=2;++k)
    58                   temp[i][j]=(temp[i][j]+a[i][k]*a[k][j]%mod)%mod;
    59             }
    60         for(int i=1;i<=2;++i)
    61           for(int j=1;j<=2;++j)
    62              a[i][j]=temp[i][j];
    63         
    64         n>>=1;
    65     }
    66     return f[1][1];
    67 }
    68 
    69 ll mi(ll x,ll c,ll qw)
    70 {
    71     ll ans=1;
    72     while(c)
    73     {
    74         if(c&1)
    75           ans=(ans*x)%qw;
    76         x=(x*x)%qw;
    77         c>>=1;
    78     }
    79     return ans;
    80 }
    81 
    82 int main(){
    83     scanf("%d%d",&m,&p);
    84     for(int i=1;i<=m;++i)
    85     {
    86         scanf("%d%lld",&n,&q);
    87         chu();
    88         mod=oula(q);
    89         ll temp=cheng();
    90         printf("%lld
    ",mi(p,temp,q)%q);
    91         
    92     }
    93     return 0;
    94 }
    code
  • 相关阅读:
    Leetcode | Work Break I & II
    X-Japan
    Leetcode | Gas Station
    jstring, String, char* 变换函数
    动态链接库的创建
    C语言实现md5函数代码
    ARM汇编指令集
    2014年 各类黑客工具包
    ARM汇编指令的一些总结-转
    ARM指令集学习总结-转载
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7259883.html
Copyright © 2011-2022 走看看