password
发布日期:2025-05-01 22:45:41 浏览次数:2 分类:技术文章

本文共 3010 字,大约阅读时间需要 10 分钟。

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
2 #include
3 #include
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

 

转载于:https://www.cnblogs.com/A-LEAF/p/7259883.html

上一篇:PAT (Basic Level) Practice 乙级1001-1020
下一篇:passwd命令限制用户密码到期时间

发表评论

最新留言

路过按个爪印,很不错,赞一个!
[***.219.124.196]2025年04月10日 12时03分06秒