1. 程式人生 > >7.30考試password

7.30考試password

lap algorithm 通過 水題 == n) 什麽 bre ons

  先說地球人都看得出來的,該數列所有數都是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
View Code

7.30考試password