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想对一组数据进行加密,但他对程序设计不太感兴趣,请你帮助他设计一个数据加密程序。
第一行读入m,p。其中m表示数据个数,p用来生成数列E。 以下有m行,每行有2个整数n,q。n为待加密数据,q为密钥。 数据范围: 0 < p n< 2^31 0 < q < p 0 < m <= 5000。
将加密后的数据按顺序输出到文件 第i行输出第i个加密后的数据。 输入样例1 2 7 4 5 4 6 输入样例2 4 7 2 4 7 1 6 5 9 3
1 #include<cmath>
2 #include<queue>
3 #include<cstdio>
4 #include<cstdlib>
5 #include<cstring>
6 #include<iostream>
7 #include<algorithm>
8 using namespace std;
9 int m,n;
10 long long mo,p;
11 long long f[5],a[5][5];
12 long long c[5];
13 long long phi;
14 long long OL(long long t){
15 long long k=t;
16 for(int i=2;i*i<=t;i++){
17 if(t%i==0){
18 k=k-k/i;
19 while(t%i==0){
20 t/=i;
21 }
22 }
23 }
24 if(t>1){
25 k=k-k/t;
26 }
27 return k;
28 }
29 void cheng1(){
30 memset(c,0,sizeof(c));
31 for(int i=1;i<=2;i++){
32 for(int j=1;j<=2;j++){
33 c[i]+=f[j]*a[j][i];
34 c[i]%=phi;
35 }
36 }
37 for(int i=1;i<=2;i++){
38 f[i]=c[i];
39 }
40 }
41 long long d[5][5];
42 void cheng2(){
43 memset(d,0,sizeof(d));
44 for(int k=1;k<=2;k++){
45 for(int i=1;i<=2;i++){
46 for(int j=1;j<=2;j++){
47 d[i][j]+=a[i][k]*a[k][j];
48 d[i][j]%=phi;
49 }
50 }
51 }
52 for(int i=1;i<=2;i++){
53 for(int j=1;j<=2;j++){
54 a[i][j]=d[i][j];
55 }
56 }
57 }
58 int main(){
59 //freopen("a07.in","r",stdin);
60 //freopen("password.in","r",stdin);
61 //freopen("password.out","w",stdout);
62 scanf("%d%lld",&m,&p);
63 for(int i=1;i<=m;i++){
64 scanf("%d%lld",&n,&mo);
65 f[1]=1; f[2]=1; a[1][1]=1; a[1][2]=1; a[2][1]=1; a[2][2]=0;
66 if(n<=2){
67 printf("%lld\n",p%mo);
68 continue;
69 }
70 phi=OL(mo);
71 n-=2;
72 while(n){
73 if(n&1){
74 cheng1();
75 }
76 cheng2();
77 n=(n>>1);
78 }
79 long long t=f[1];
80 long long ans=1,ch=p;
81 while(t){
82 if(t&1){
83 ans*=ch;
84 ans%=mo;
85 }
86 ch*=ch;
87 ch%=mo;
88 t=(t>>1);
89 }
90 printf("%lld\n",ans%mo);
91 }
92 return 0;
93 }