7.30考试password
先说地球人都看得出来的,该数列所有数都是p的斐波那契数列中所对应的数的次幂,所以一开始都以为是道水题,然而斐波那契数列增长很快,92以后就爆long long ,所以要另谋出路,于是乎向Ren_ivan大犇学了扩展欧拉定理:(a^b)%p=(a^(b%φ(p)))%p不要问我为什么,我也不会证。
所以这道题就变成简单的数学题了,首先筛出sqpt(1<<31)以内的素数,不必担心复杂度,线筛还是挺快的。然后针对每一个q求出它的欧拉函数,再通过矩阵快速幂求出对应的斐波那契数列,再用快速幂最终处理即可,简单粗暴,唯一的难点就是扩展欧拉定理。
考试的时候除了扩展欧拉定理都想到了,只能打完快速幂,预处理出斐波那契数列后硬杠,结果当时有点贪心,是否直接使用斐波那契数列的边界开的大了点,爆了long long ,丢了2个点的分,又一次身败名裂……
(本代码函数名都为拼音+英文,见笑了)。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<queue> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 long long m,p,zz,n; 10 long long ol[1<<17]; 11 bool fss[1<<17]; 12 long long ss[1<<17]; 13 void olhs(){ 14 ol[1]=1; 15 for(long long i=2;i<=n;i++) 16 { 17 if(!fss[i]) 18 { 19 zz++; 20 ss[zz]=i; 21 ol[i]=i-1; 22 } 23 for(long long j=1;j<=zz;j++) 24 { 25 long long x=i*ss[j]; 26 if(x>n)break; 27 fss[x]=1; 28 if(i%ss[j]==0) 29 { 30 ol[x]=ol[i]*ss[j]; 31 break; 32 } 33 else 34 ol[x]=ol[i]*(ss[j]-1); 35 } 36 } 37 } 38 long long ksm(long long x,long long y,long long z){ 39 long long ans=1; 40 long long yy=y; 41 if(!x) 42 return 1%z; 43 while(x) 44 { 45 if((x&1)) ans=(ans*yy)%z; 46 yy=(yy*yy)%z; 47 x/=2; 48 } 49 return ans; 50 } 51 long long getol(long long x){ 52 long long sum=x; 53 for(int i=1;(long long)((long long)ss[i]*(long long)ss[i])<=x;i++) 54 if(!(x%(long long)ss[i])){ 55 sum=sum-sum/(long long)ss[i]; 56 while(!(x%ss[i]))x/=(long long)ss[i]; 57 } 58 if(x>1)sum=sum-sum/x; 59 return sum; 60 } 61 long long mo; 62 struct no{ 63 long long x[5][5]; 64 no operator *(const no &a) 65 { 66 no ans; 67 ans.x[1][1]=ans.x[1][2]=ans.x[2][1]=ans.x[2][2]=0; 68 for(long long i=1;i<=2;i++) 69 { 70 for(long long j=1;j<=2;j++) 71 { 72 for(long long k=1;k<=2;k++) 73 { 74 ans.x[i][j]+=x[i][k]*a.x[k][j]; 75 } 76 ans.x[i][j]%=mo; 77 } 78 } 79 return ans; 80 } 81 }; 82 long long getfb(long long x){ 83 no a; 84 if(x==-1||x==0)return 1; 85 a.x[1][1]=a.x[1][2]=a.x[2][1]=1; 86 a.x[2][2]=0; 87 no ans; 88 ans.x[1][1]=ans.x[2][2]=1; 89 ans.x[1][2]=ans.x[2][1]=0; 90 while(x) 91 { 92 if(x&1) 93 { 94 ans=ans*a; 95 } 96 a=a*a; 97 x=x>>1; 98 } 99 100 return ans.x[1][1]+ans.x[1][2]; 101 } 102 long long work(long long x,long long y){ 103 mo=getol(y); 104 long long xx=getfb(x-2); 105 return ksm(xx,p,y); 106 } 107 int main(){ 108 long long xx=(1<<31)-1; 109 n=sqrt(xx); 110 olhs(); 111 scanf("%lld%lld",&m,&p); 112 while(m--) 113 { 114 long long x,y; 115 scanf("%lld%lld",&x,&y); 116 printf("%lld\n",work(x,y)); 117 } 118 //while(1); 119 return 0; 120 } 121