Password

问题 A: Password

时间限制: 1 Sec  内存限制: 64 MB

题目描述

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 
2 7 
4 5 
4 6 
输入样例2 
4 7 
2 4 
7 1 
6 5 
9 3 

样例输出

输出样例1
3
1

输出样例2
3
0
1
1

提示

一摩不会的知识点凑到一块也是醉了(⊙﹏⊙)b

  知识点详总:快速线性筛素(唯一会的),扩展欧拉,矩阵快速幂求斐波那契额数

先附上代码:

  

 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  

 

posted @ 2017-07-30 21:37  Hzoi_Maple  阅读(167)  评论(0编辑  收藏  举报