[补档]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
原文地址:https://www.cnblogs.com/hzoi-mafia/p/7277680.html