HDU - 6030 矩阵快速幂 +多组输入快速幂板子
题意:一个项链用n个珠子构成,是一个条而不是一个环,由红和蓝两种颜色构成,要求以任意点为起点向后的素数个珠子中,保证红颜色的大于等于蓝颜色的,问你有多少种方案满足,范围:n(2≤n≤1018)
推导过程参考链接:https://blog.csdn.net/nobleman__/article/details/78345142
我们知道最小的素数就是2了,由于考虑到是从任意一点开始,如果到了某一点往后没有两个的话就直接符合了,所以在n = 1的情况下,答案为2,也就是一个红,或一个蓝,首先我们可以在(n-1)项的基础上在末尾再添加一个红色,显然符合题意,其次我们考虑下因为最小的素数为2,所以不允许出现【蓝红蓝】的情况,但是可以出现【蓝红红蓝】的情况,所以当(n-1)项中后面连续两个是红色的时候我们就可以在末尾添加一个蓝色,我们可以发现(n-1)项中末尾是【红红】的数目恰好等于(n-3)的数目
————————————————
推导方程为:Fn=F(n-1)+F(n-3)
|Fn F(n-1) F(n-2)| = |F(n-1) F(n-2) F(n-3)| * |1 1 0|
|0 0 1|
|1 0 0|
代码:
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define mod(x) ((x)%MOD) 4 5 using namespace std; 6 7 const ll MOD = 1e9 + 7; 8 9 struct mat 10 { 11 ll m[3][3]; 12 } a,ans,unit; 13 ll n; 14 15 void init() 16 { 17 memset(a.m,0,sizeof(a.m)); 18 a.m[0][0] = 1; 19 a.m[0][1] = 1; 20 a.m[1][2] = 1; 21 a.m[2][0] = 1; 22 } 23 24 mat operator * (mat m1,mat m2) 25 { 26 mat t; 27 ll r; 28 for(int i = 0; i < 3; i++) 29 { 30 for(int j = 0; j < 3; j++) 31 { 32 r = 0; 33 for(int k = 0; k < 3; k++) 34 { 35 r = mod(r*1ll + mod(m1.m[i][k]*1ll*m2.m[k][j])); 36 } 37 t.m[i][j] = r; 38 } 39 } 40 return t; 41 } 42 43 mat quick_pow(ll x) 44 { 45 mat t; 46 for(int i=0;i<3;++i) 47 for(int j=0;j<3;++j) 48 t.m[i][j]=0; 49 for(int i=0;i<3;++i) 50 t.m[i][i]=1; 51 while(x) 52 { 53 if(x & 1) t = t*a; 54 a = a*a; 55 x >>= 1; 56 } 57 return t; 58 } 59 60 int main() 61 { 62 memset(unit.m,0,sizeof(unit.m)); 63 unit.m[0][0] = 4; 64 unit.m[0][1] = 3; 65 unit.m[0][2] = 2; 66 ios_base::sync_with_stdio(0); 67 int T; 68 cin>>T; 69 init(); 70 while(T--) 71 { 72 init(); 73 cin>>n; 74 if(n < 4) 75 { 76 if(n == 1) cout<<2<<endl; 77 if(n == 2) cout<<3<<endl; 78 if(n == 3) cout<<4<<endl; 79 continue; 80 } 81 ans = quick_pow(n-3); 82 cout<<((unit.m[0][0]*ans.m[0][0])%MOD+(unit.m[0][1]*ans.m[1][0])%MOD+(unit.m[0][2]*ans.m[2][0])%MOD)%MOD<<endl; 83 } 84 return 0; 85 }