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想对一组数据进行加密,但他对程序设计不太感兴趣,请你帮助他设计一个数据加密程序。
输入
第一行读入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
solution:
又是一道数学题,很智障的,我们会发现素数p的次幂其实是个斐波那契额数列。
首先需要用矩阵快速幂单个求出每一次的n对应的斐波那契额数列中的数。
这时需要用到欧拉定理:a^x=a^(x%phi(q))%q,a与q互素,其中因为题面中说q<p,所以满足a与q互素
如果不这样降幂会炸掉,考试的时候亲自尝试过。。。。。。
得到降幂后的x,再用一个快速幂就可以啦
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 #define int long long 7 __attribute__((optimize("O3")))int read() { 8 int s=0,f=1; 9 char ch=getchar(); 10 while(ch>'9'||ch<'0') { 11 if(ch=='-') { 12 f=-1; 13 } 14 ch=getchar(); 15 } 16 while(ch>='0'&&ch<='9') { 17 s=(s<<1)+(s<<3)+(ch^48); 18 ch=getchar(); 19 } 20 return s*f; 21 } 22 __attribute__((optimize("O3")))int get_phi(int t) { 23 int kk=t; 24 for(int i=2; i*i<=t; i++) { 25 if(t%i==0) { 26 kk-=kk/i; 27 while(t%i==0) { 28 t/=i; 29 } 30 } 31 } 32 if(t>1) { 33 kk-=kk/t; 34 } 35 return kk; 36 } 37 __attribute__((optimize("O3")))void fast(long long a[][3],long long b[][3],int q) { 38 long long temp[3][3]= {0}; 39 for(int i=1; i<=2; i++) { 40 for(int j=1; j<=2; j++) { 41 for(int k=1; k<=2; k++) { 42 temp[i][j]=(temp[i][j]+a[i][k]*b[k][j])%q; 43 } 44 } 45 } 46 b[1][1]=temp[1][1]%q; 47 b[1][2]=temp[1][2]%q; 48 b[2][1]=temp[2][1]%q; 49 b[2][2]=temp[2][2]%q; 50 } 51 __attribute__((optimize("O3")))long long speed(int i,int q) { 52 long long sin[3][3],a[3][3]; 53 sin[1][1]=1; 54 sin[2][1]=1; 55 sin[1][2]=1; 56 sin[2][2]=0; 57 a[1][1]=1; 58 a[1][2]=0; 59 a[2][1]=0; 60 a[2][2]=1; 61 for(; i; i>>=1,fast(sin,sin,q)) { 62 if(i&1) { 63 fast(sin,a,q); 64 } 65 } 66 return a[1][2]; 67 } 68 int m,p,q,n; 69 __attribute__((optimize("O3")))long long mul(int a,long long t,int mod) { 70 long long ans=1; 71 for(; t; t>>=1,(a=a*a%mod)) { 72 if(t&1) { 73 (ans=a*ans%mod); 74 } 75 } 76 return ans; 77 } 78 __attribute__((optimize("O3")))signed main() { 79 m=read(); 80 p=read(); 81 for(int i=1; i<=m; i++) { 82 n=read(); 83 q=read(); 84 int ji=get_phi(q); 85 int x=speed(n,ji); 86 x=x%ji; 87 long long ans=mul(p,x,q)%q; 88 printf("%lld\n",ans); 89 } 90 return 0; 91 }