欧拉函数+矩阵快速幂 Password
2017-07-30 19:13
190 查看
问题 A: Password
时间限制: 1 Sec 内存限制: 64 M
题目描述
Rivest是密码学专家。近日他正在研究一种数列E = {E[1],E[2],……,E }, 且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
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
p的多少次幂显然是一个斐波那契数列,考虑用矩阵快速幂,但会炸ll,
欧拉函数扩展 p^phi(q)%q=1,这样,求出phi(q),乘的时候%一下。
求出p^f 后,再用普通快速幂求出ans即可
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<cmath> #include<algorithm> #define ll long long using namespace std; ll m,p,n,q,pp,inf=(1<<31)-1,phi[46400],mark[46400],tot,prime[40000]; ll k; struct node { ll f[2][2]; node(){ memset(f,0,sizeof(f)); } } a,b; ll read() { ll sum=0,f=1;char x=getchar(); while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();} while(x>='0'&&x<='9')sum=sum*10+x-'0',x=getchar(); return sum*f; } void get_phi() { phi[1]=1; for(ll i=2;i<=sqrt(inf);i++) { if(!mark[i]) { prime[++tot]=i; phi[i]=i-1; } for(int j=1;j<=tot;j++) { if(i*prime[j]>sqrt(inf))break; mark[i*prime[j]]=1; if(!(i%prime[j])) { phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } } ll pphi(ll x) { ll t=x; for(ll i=1;prime[i]*prime[i]<=t;i++) if(!(x%prime[i])) { t=t-t/prime[i]; while(!(x%prime[i])) x/=prime[i]; } if(x>1) t=t-t/x; return t; } node cheng(node a,node b) { node c; for(int i=0;i<2;i++) for(int j=0;j<2;j++) { for(int l=0;l<2;l++) { c.f[i][j]+=a.f[i][l]*b.f[l][j]; c.f[i][j]%=k; } } return c; } int main() { //freopen("password.in","r",stdin); //freopen("password.out","w",stdout); m=read();p=read(); get_phi(); while(m--) { n=read();q=read();pp=p; if(q>sqrt(inf)) k=pphi(q); else k=phi[q]; a.f[0][0]=0;a.f[1][0]=1;a.f[1][1]=0;a.f[0][1]=0; b.f[0][0]=1;b.f[0][1]=1;b.f[1][0]=1;b.f[1][1]=0; node s; for(int i=0;i<2;i++) for(int j=0;j<2;j++) s.f[i][j]=(i==j); while(n) { if(n&1)s=cheng(b,s); b=cheng(b,b); n/=2; } s=cheng(s,a); n=s.f[0][0]; ll ans=1; while(n) { if(n&1)ans=(ans*pp)%q; pp=(pp*pp)%q; n/=2; } printf("%lld\n",ans%q); } }
相关文章推荐
- bzoj 1409 Password 矩阵快速幂+欧拉函数
- bzoj 1409 Password 矩阵快速幂+欧拉函数
- HDU 2865 Birthday Toy polya 矩阵快速幂 欧拉函数
- hdu4549 M斐波那契数列 【矩阵快速幂+快速幂+欧拉函数降次】
- HDU 5895 Mathematician QSC (矩阵快速幂 + 逆元应用 + 指数循环节 + 欧拉函数)
- HDU 3221 矩阵快速幂+欧拉函数+降幂公式降幂
- NOIP模拟题 2016.11.8 (2) [线段树] [动态逆序对] [矩阵快速幂] [数论] [欧拉函数]
- hdu-5868 Different Circle Permutation 矩阵快速幂 + 欧拉函数 + polya计数定理
- 2016Shenyang网络预选赛1004 / HDU5895 (矩阵快速幂+欧拉函数降幂)
- hdu 5868 矩阵快速幂+burnside引理 +欧拉函数+乘法逆元
- hdu 5895(矩阵快速幂+欧拉函数)
- hdu5667 Sequence 【矩阵快速幂+欧拉函数降次】
- HDU 4549 矩阵快速幂+快速幂+欧拉函数
- HDOJ M斐波那契数列 4549【矩阵快速幂+快速幂+费马小定理+欧拉函数】
- HDU 5895 矩阵快速幂+欧拉函数
- HDU 5667 Sequence【矩阵快速幂】【欧拉函数】
- hdu 5667(矩阵快速幂+欧拉函数)
- HDU6030 Happy Necklace(矩阵快速幂)
- ZOJ 2974 Just Pour the Water(矩阵快速幂)
- POJ3735 Training little cats(矩阵快速幂)