Codevs 加密算法

来源:互联网 发布:陌生网友找我淘宝开店 编辑:程序博客网 时间:2024/05/22 13:37

题目描述 Description
Rivest是密码学专家。近日他正在研究一种数列E={E[1],E[2],……,E[n]},
且E[1]=E[2]=p(p为一个质数),E[i]=E[i-2]*E[i-1]
例如{2,2,4,8,32,256,8192,……}就是p=2的数列。在此基础上他又设计了一种加密
算法,该算法可以通过一个密钥q将一个正整数n加密成另外一个正整数d,计
算公式为:d=E[n] mod q。现在Rivest想对一组数据进行加密,但他对程序设计不太
感兴趣,请你帮助他设计一个数据加密程序。

输入描述 Input Description
读入m,p。其中m表示数据个数,p用来生成数列E。
以下有m行,每行有2个整数n,q。n为待加密数据,q为密钥。
m,p,n,q都在int内
输出描述 Output Description
将加密后的数据按顺序输出到文件a.out。
第i行输出第i个加密后的数据。

样例输入 Sample Input
2 7
4 5
4 6

样例输出 Sample Output
3
1

这道题恶心得不得了。。说做法也简单,就是bzoj3884: 上帝与集合的正确用法 加上斐波那契矩阵就解决了。但是实现起来不是一般的恶心。。利用斐波那契矩阵+降幂大法我们可以解决p^fib[i]的问题,那么剩下的我们只需要计算一个快速幂就得到了答案。(直接降幂大法递归(推)处理其实不用写矩阵<-比如我)不知道降幂大法的可以自行百度上帝与集合的正确用法,这里就不多做解释。。。。。(毕竟我懒)
安利一发博客

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 100000typedef long long LL;LL m,q,n,mod;typedef LL mat[2][2];mat a,b,c;LL pow_mod(LL x,LL y,LL mod){    LL ret=1;    while (y)    {        if (y&1)ret=ret*x%mod;        x=x*x%mod;        y>>=1;    }    return ret;}int prime[MAXN],topp=-1;bool pflag[MAXN];void init(){    for (int i=2;i<MAXN;i++)    {        if (!pflag[i])        prime[++topp]=i;        for (int j=0;j<=topp && i*prime[j]<MAXN;j++)        {            pflag[i*prime[j]]=true;            if (i%prime[j]==0)break;        }    }}LL get_phi(LL x){    LL ret=1;    for (int i=0;i<=topp && (LL)prime[i]*prime[i]<=x;i++)    {        if (x%prime[i]==0)        {            x/=prime[i];            ret*=prime[i]-1;            while (x%prime[i]==0)            {                x/=prime[i];                ret*=prime[i];            }        }    }    if (x!=1)    ret*=x-1;    return ret;}int main(){    LL i,j,k,x,y,z;    scanf("%lld %lld",&m,&q);    LL phi_mod;    init();    while (m--)    {        scanf("%lld%lld",&n,&mod);        if (mod==1)        {            printf("0\n");            continue;        }        if (mod==q)        {            printf("0\n");            continue;        }        phi_mod=get_phi(mod);        a[0][0]=a[0][1]=a[1][0]=1;        a[1][1]=0;        b[0][0]=b[1][1]=1;        b[1][0]=b[0][1]=0;        n--;        while (n)        {            if (n&1)            {                memset(c,0,sizeof(c));                for (i=0;i<2;i++)                for (j=0;j<2;j++)                for (k=0;k<2;k++)                c[i][j]=(c[i][j]+a[i][k]*b[k][j]%phi_mod)%phi_mod;                memcpy(b,c,sizeof(b));            }            memset(c,0,sizeof(c));            for (i=0;i<2;i++)            for (j=0;j<2;j++)            for (k=0;k<2;k++)            c[i][j]=(c[i][j]+a[i][k]*a[k][j]%phi_mod)%phi_mod;            memcpy(a,c,sizeof(c));            n>>=1;        }        printf("%lld\n",pow_mod(q,b[0][0],mod));}}
0 0
原创粉丝点击