问题 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 ",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 ",ans); 91 } 92 } 93 // while(1); 94 return 0; 95 } 96