password

Description
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 想对一组数据进行加密,但他对程序设计不太感兴趣,请你帮
助他设计一个数据加密程序。
Input
第一行读入m,p。其中m 表示数据个数,p 用来生成数列E。以下有m 行,每行有2 个
整数n,q。n 为待加密数据,q 为密钥。数据范围: 0 < p n< 2^31 0 < q < p 0 < m <= 5000。
Output
将加密后的数据按顺序输出到文件第i 行输出第i 个加密后的数据。输入样例1 2 7 4 5 4
6 输入样例2 4 7 2 4 7 1 6 5 9 3
Sample Input
输入样例1
2 7
4 5
4 6
输入样例2
4 7
2 4
7 1
6 5
9 3
Sample Output
输出样例1
31
输出样例2
3011

solution

计算公式为:d=E[n] mod q

                     d=p^(fibonaqi[n]) mod q

所以 要 求斐波那契的第n项,但是我们发现long long也只能开到九十多项,想到了 降幂

这里就用到了  欧拉定理: a^b%k = a^(b%φ(k)) % k                  gcd(a,k)==1

                                         a^b%k = a^(b%φ(k)+φ(k)) % k          gcd(a,k)!=1

用这段神奇的code 来求 φ(k)

 1 ll oula(ll t)
 2 {
 3   ll kk=t;
 4   for(ll i=2;i*i<=t;++i)
 5   if(t%i==0)
 6   {
 7     kk=kk-kk/i;
 8     while(t%i==0)
 9       t/=i;
10   }
11   if(t>1)kk=kk-kk/t;
12   return kk;
13 }
神奇的code

再用矩阵快速幂 求指数的斐波那契

最后快速幂即可      (注意要用long long)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #define ll long long
 5 #define mem(a,b) memset(a,b,sizeof(a))
 6 using namespace std;
 7 
 8 int m,p,n;
 9 ll q;
10 ll f[6][6],a[6][6],temp[6][6];
11 ll mod;
12 
13 ll oula(ll t)
14 {
15     ll kk=t;
16     for(ll i=2;i*i<=t;++i)
17       if(t%i==0)
18       {
19             kk=kk-kk/i;
20             while(t%i==0)
21               t/=i;
22         }
23     if(t>1)kk=kk-kk/t;
24     return kk;
25 }
26 
27 inline void chu()
28 {
29     mem(f,0);
30     mem(a,0);
31     f[1][1]=1;f[2][2]=1;
32     a[1][1]=1;a[1][2]=1;a[2][1]=1;
33 }
34 
35 inline ll cheng()
36 {
37     --n;
38     while(n)
39     {
40         if(n&1)
41         {
42             for(int i=1;i<=2;++i)
43               for(int j=1;j<=2;++j)
44               {
45                     temp[i][j]=0;
46                     for(int k=1;k<=2;++k)
47                       temp[i][j]=(temp[i][j]+f[i][k]*a[k][j]%mod)%mod;
48                 }
49             for(int i=1;i<=2;++i)
50               for(int j=1;j<=2;++j)
51                 f[i][j]=temp[i][j];
52         }
53         for(int i=1;i<=2;++i)
54           for(int j=1;j<=2;++j)
55           {
56                 temp[i][j]=0;
57                 for(int k=1;k<=2;++k)
58                   temp[i][j]=(temp[i][j]+a[i][k]*a[k][j]%mod)%mod;
59             }
60         for(int i=1;i<=2;++i)
61           for(int j=1;j<=2;++j)
62              a[i][j]=temp[i][j];
63         
64         n>>=1;
65     }
66     return f[1][1];
67 }
68 
69 ll mi(ll x,ll c,ll qw)
70 {
71     ll ans=1;
72     while(c)
73     {
74         if(c&1)
75           ans=(ans*x)%qw;
76         x=(x*x)%qw;
77         c>>=1;
78     }
79     return ans;
80 }
81 
82 int main(){
83     scanf("%d%d",&m,&p);
84     for(int i=1;i<=m;++i)
85     {
86         scanf("%d%lld",&n,&q);
87         chu();
88         mod=oula(q);
89         ll temp=cheng();
90         printf("%lld\n",mi(p,temp,q)%q);
91         
92     }
93     return 0;
94 }
code

 

posted @ 2017-07-30 18:33  A_LEAF  阅读(359)  评论(0编辑  收藏  举报