18.09.21模拟赛T1。
这实际上是zhx出的增强版。
考试的时候写了15分暴力,没推出来式子......
先看一下题:
题面是一样的。
只不过,网上那道题的数据范围好小啊。
所以出题人zhx大佬把n的范围改成了1^18,把取模数改成了1^18+7。
式子:f[x]=2*f[x-1]+f[x-2]
矩阵乘法优化:
f[k-1] f[k-2] 乘 2 1 等于 f[k] f[k-1]
0 0 1 0 0 0
再写个快速乘就行了。
这么简单的题我居然没切......面壁。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ll long long 5 using namespace std; 6 7 ll n; 8 ll m=(ll)(1e18)+7; 9 10 struct matrix 11 { 12 ll a[2][2]; 13 }f,g; 14 15 ll multi(ll q,ll w) 16 { 17 ll ret=0; 18 while(w) 19 { 20 if(w&1)ret=(ret+q)%m; 21 q=(q+q)%m; 22 w>>=1; 23 } 24 return ret; 25 } 26 27 matrix multi(matrix q,matrix w) 28 { 29 matrix e; 30 for(int i=0;i<=1;i++) 31 { 32 for(int j=0;j<=1;j++) 33 { 34 e.a[i][j]=0; 35 for(int k=0;k<=1;k++) 36 { 37 e.a[i][j]=(e.a[i][j]+multi(q.a[i][k],w.a[k][j]))%m; 38 } 39 } 40 } 41 return e; 42 } 43 44 matrix ksm(matrix b,ll p) 45 { 46 matrix ret=b; 47 p--; 48 while(p) 49 { 50 if(p&1)ret=multi(ret,b); 51 b=multi(b,b); 52 p>>=1; 53 } 54 return ret; 55 } 56 57 int main() 58 { 59 freopen("RSA.in","r",stdin); 60 freopen("R5A.out","w",stdout); 61 scanf("%I64d",&n); 62 f.a[0][0]=0,f.a[0][1]=1; 63 g.a[0][0]=2; 64 g.a[0][1]=g.a[1][0]=1; 65 g=ksm(g,n); 66 f=multi(f,g); 67 printf("%I64d",f.a[0][0]); 68 fclose(stdin); 69 fclose(stdout); 70 return 0; 71 }