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<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<cmath>
6 using namespace std;
7 const int N=70000;
8 struct jz{
9 long long a[3][3];
10 jz(){a[1][1]=a[1][2]=a[2][1]=a[2][2]=0;}
11 }T,G;
12 int read(){
13 int sum=0;char ch=getchar();
14 while(ch<‘0‘||ch>‘9‘) ch=getchar();
15 while(ch>=‘0‘&&ch<=‘9‘) {sum=sum*10+ch-‘0‘;ch=getchar();}
16 return sum;
17 }
18 int m,p,tot,n,q;
19 int pri[100000];bool prime[100000];
20 void build(){
21 prime[1]=1;
22 for(int i=2;i<N;++i){
23 if(!prime[i])
24 pri[++tot]=i;
25 for(int j=1;j<=tot&&i*pri[j]<N;++j){
26 prime[i*pri[j]]=1;
27 if(!(i%pri[j])) break;
28 }
29 }
30 }
31 int get_phi(int x){
32 int tmp=x;
33 int top=(int)sqrt(x);
34 for(int i=1;pri[i]<=top;++i){
35 if(x%pri[i]==0){
36 tmp-=tmp/pri[i];
37 while(!(x%pri[i])) x/=pri[i];
38 }
39 }
40 if(x>1) tmp-=tmp/x;
41 return tmp;
42 }
43 jz jzc(jz G,jz T,long long mod){
44 jz ans;
45 for(int i=1;i<=2;++i)
46 for(int j=1;j<=2;++j)
47 for(int k=1;k<=2;++k){
48 ans.a[i][j]+=G.a[i][k]*T.a[k][j];
49 ans.a[i][j]%=mod;
50 }
51 return ans;
52 }
53 jz ks(jz G,int n,int mod){
54 jz ans;ans.a[1][1]=ans.a[2][2]=1;
55 while(n){
56 if(n&1)
57 ans=jzc(G,ans,mod);
58 n>>=1;
59 G=jzc(G,G,mod);
60 }
61 return ans;
62 }
63 long long power(long long p,long long n,long long mod){
64 long long sq=1;
65 while(n){
66 if(n&1)
67 sq=(sq*p)%mod;
68 n>>=1;
69 p=(p*p)%mod;
70 }
71 return sq%q;
72 }
73 int main(){
74 //freopen("password.in","r",stdin);
75 //freopen("password.out","w",stdout);
76 m=read();p=read();
77 T.a[1][1]=T.a[1][2]=T.a[2][1]=1;T.a[2][2]=0;
78 build();
79 for(int i=1;i<=m;++i){
80 n=read();q=read();
81 int phi=get_phi(q);
82 if(n==1||n==2)
83 printf("%lld\n",p%q);
84 else{
85 G=T;
86 G=ks(G,n-2,phi);
87 long long sum=0;
88 sum=G.a[1][1]+G.a[1][2];
89 long long ans=power(p,sum,q);
90 printf("%lld\n",ans);
91 }
92 }
93 // while(1);
94 return 0;
95 }
96