• [补档]Password


    Password

    题目

    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个加密后的数据。

    SAMPLE

    INPUT1

    2 7
    4 5
    4 6

    OUTPUT1

    3
    1

    INPUT2

    4 7
    2 4
    7 1
    6 5
    9 3

    OUTPUT2

    3
    0
    1
    1

    解题报告

    考试时候本以为推了个正解,又强行推出了实现,结果= =
    还不如打个暴力
    正解:
    首先写个公式:
    其中,phi(p)为p的欧拉函数。
    不要问我怎么证,我不会
    然后,我们可以得出,要求的显然就是p^fib(i)%q,其中fib(i)为斐波那契数列的第i项。
    显然,正经递推斐波那契是会T的。所以我们考虑优化,显然可以用矩阵快速幂解决问题。
    那么,剩下的就很简单了。直接快速幂就可以解决了。
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 typedef long long L;
     6 inline int read(){
     7     int sum(0);
     8     char ch(getchar());
     9     for(;ch<'0'||ch>'9';ch=getchar());
    10     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
    11     return sum;
    12 }
    13 L m,p,n,q;
    14 L fib;
    15 L unit[2][2],start[2][2];
    16 inline void multi(L a[][2],L b[][2],L mod){
    17     L tmp[2][2]={0};
    18     for(int i=0;i<2;i++)
    19         for(int j=0;j<2;j++)
    20             for(int k=0;k<2;k++)
    21                 tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%mod;
    22     for(int i=0;i<2;i++)
    23         for(int j=0;j<2;j++)
    24             b[i][j]=tmp[i][j];
    25 }
    26 inline int get_phi(L x){
    27     L ret(x);
    28     for(int i=2;i*i<=x;i++)
    29         if(x%i==0){
    30             ret=ret-ret/i;
    31             while(x%i==0)
    32                 x/=i;
    33         }
    34     if(x>1)
    35         ret=ret-ret/x;
    36     return ret;
    37 }
    38 inline L fi(L p,L mod){
    39 /*  if(p==0)
    40         return 0;
    41     if(p==1||p==2)
    42         return 1;*/
    43     start[0][0]=start[1][0]=start[0][1]=1,start[1][1]=0;
    44     unit[0][0]=unit[1][1]=1,unit[1][0]=unit[0][1]=0;
    45     while(p){
    46         if(p&1)
    47             multi(start,unit,mod);
    48         multi(start,start,mod);
    49         p>>=1;
    50     }
    51     return unit[0][1];
    52 }
    53 L mod;
    54 inline L qpow(L a,L p,L mod){
    55     L ret(1);
    56     while(p){
    57         if(p&1)
    58             ret*=a,ret%=mod;
    59         a*=a,a%=mod;
    60         p>>=1;
    61     }
    62     return ret;
    63 }
    64 int main(){
    65 //  freopen("1.in","r",stdin);
    66 //  freopen("1.out","w",stdout);
    67     m=read(),p=read();
    68     while(m--){
    69         n=read(),q=read();
    70         mod=get_phi(q);
    71         fib=fi(n,mod);
    72         fib%=mod;
    73         printf("%lld
    ",qpow(p,fib,q)%q);
    74     }
    75 }
    View Code
  • 相关阅读:
    C#调用webservice 时如何传递实体对象
    Gridview实现突出显示某一单元格的方法
    oracle数据库存储过程分页
    GridView合并表头多重表头
    Gridview中实现求和统计功能
    C#封装的一个JSON操作类
    C#通过StreamWriter对象实现把数值内容写到记事本
    Android CTS
    离线安装eclipse maven插件
    selenium2 页面对象模型Page Object
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7277680.html
Copyright © 2020-2023  润新知