bzoj 1409 Password

题目大意:

一种数列E = {E[1],E[2],……,E[n]}

且E[1] = E[2] = p(p为一个质数),E[i] = E[i-2]*E[i-1] (若2<i<=n)

在此基础上他又设计了一种加密算法,该算法可以通过一个密钥q (q < p)将一个正整数n加密成另外一个正整数d,计算公式为:d = E[n] mod q

思路:

首先可以想到快速幂

然后就是求一个数的斐波那契n项次方

因为斐波那契n项很大 所以log n很大会炸

因为p^phi(q)%q=1,注意q不一定是质数

所以只需要求出 f[i]%phi(q) 然后快速幂

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<vector>
 8 #include<queue>
 9 #define inf 2139062143
10 #define ll long long
11 #define MAXN 100100
12 using namespace std;
13 inline ll read()
14 {
15     ll x=0,f=1;char ch=getchar();
16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 ll p[MAXN],ntp[MAXN],cnt,n,m,mod,T,m1;
21 struct mat {ll num[2][2];};  
22 mat mul(mat x,mat y)  
23 {  
24     mat res;
25     memset(res.num,0,sizeof(res.num));  
26     for(ll i=0;i<2;i++)  
27         for(ll j=0;j<2;j++)  
28             for(ll k=0;k<2;k++)  
29                 (res.num[i][j]+=x.num[i][k]*y.num[k][j])%=m1;
30     return res;
31 }
32 ll mat_q_pow(ll n)
33 {
34     if(n<=0) return 0;
35     mat t,res;
36     memset(res.num,0,sizeof(res.num));
37     t.num[0][0]=t.num[0][1]=t.num[1][0]=1,t.num[1][1]=0;
38     res.num[0][0]=res.num[1][1]=1;
39     while(n)
40     {
41         if(n&1) res=mul(res,t);
42         t=mul(t,t);
43         n>>=1;
44     }
45     return res.num[0][1];
46 }
47 void mem()
48 {
49     for(ll i=2;i<MAXN;i++)
50     {
51         if(!ntp[i]) p[++cnt]=i;
52         for(ll j=1;p[j]*i<MAXN;j++)
53         {
54             ntp[p[j]*i]=1;
55             if(i%p[j]==0) break;
56         }
57     }
58 }
59 void phi(ll x)
60 {
61     ll res=x;
62     for(ll i=1;p[i]*p[i]<=x;i++)
63         if(x%p[i]==0)
64         {
65             res/=p[i],res*=p[i]-1;
66             while(x%p[i]==0) x/=p[i];
67         }
68     if(x!=1) res/=x,res*=x-1;
69     m1=res;
70 }
71 ll num_q_pow(ll k,ll x)
72 {
73     ll res=1;
74     while(x)
75     {
76         if(x&1) (res*=k)%=mod;
77         (k*=k)%=mod,x>>=1;
78     }
79     return res;
80 }
81 int main()
82 {
83     T=read(),n=read();
84     mem();
85     while(T--)
86     {
87         m=read(),mod=read();
88         phi(mod);
89         printf("%lld\n",num_q_pow(n,mat_q_pow(m))%mod);
90     }
91 }
View Code

 

posted @ 2018-03-06 18:11  jack_yyc  阅读(132)  评论(0编辑  收藏  举报