hdu6030 Happy Necklace(矩陣快速冪+遞推式)
阿新 • • 發佈:2018-12-03
思路來源
https://www.cnblogs.com/bolderic/p/7216739.html
題意
給你一個長為n的珠子串,要求你給這條串塗色,
要求任意素數長度的串中,紅色數不少於藍色數,只有紅藍兩色。
問長為n的串的塗色方案數。
題解
這個遞推式還是挺好想的,就是好久不用矩陣快速冪一下愣住了。
dp寫久了小範圍的用不了矩陣快速冪的還是把自己寫傻了QAQ
注意到任意素數長度都成立,則任意2個必有1個紅珠,任意3個必有2個紅珠。
則剩下顯然能推出5個必有3個,7個必有4個…以此類推,所以只看2個和3個即可。
1 紅 藍 ans=2
2 紅紅 藍紅 紅藍 ans=3
3 紅紅紅 藍紅紅 紅藍紅 紅紅藍 ans=4
4 紅紅紅紅 藍紅紅紅 紅藍紅紅 紅紅藍紅 紅紅紅藍 藍紅紅藍 ans=6
這麼多就足以說明問題了,
注意到an至少等於an-1,
若第n個珠子為紅,an-1的方案後補一個紅珠即可,
若第n個珠子為藍,由藍藍、藍紅藍兩種情況不能出現,
說明該種情況一定由XXXXX紅紅轉移而來,XXXXX部分任意,對應an-3的方案數。
即有an=an1+an-3,矩陣快速冪一波就可以了。
=*,一波矩陣快速冪即可
心得
還是得多做題,不然反應不過來,順便屯個板子gg
程式碼
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include <map> #include <vector> #include <stack> #include <queue> #include <functional> const int INF=0x3f3f3f3f; const int maxn=1e5+10; const int mod=1e9+7; const int MOD=998244353; const double eps=1e-7; typedef long long ll; #define vi vector<int> #define si set<int> #define pii pair<int,int> #define pi acos(-1.0) #define pb push_back #define mp make_pair #define lowbit(x) (x&(-x)) #define sci(x) scanf("%d",&(x)) #define scll(x) scanf("%lld",&(x)) #define sclf(x) scanf("%lf",&(x)) #define pri(x) printf("%d",(x)) #define rep(i,j,k) for(int i=j;i<=k;++i) #define per(i,j,k) for(int i=j;i>=k;--i) #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int inf = 0x3f3f3f3f; typedef vector<long long> vec; typedef vector<vec> mat; mat mul(mat &A, mat &B){ mat C(A.size(), vec(B[0].size())); for(int i = 0; i < A.size(); i++){ for(int k = 0; k < B.size(); k++){ for(int j = 0; j < B[0].size(); j++){ C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod; } }.j,j } return C; } mat pow(mat A, ll n){ mat B(A.size(), vec(A.size())); for(int i = 0; i < A.size(); i++){ B[i][i] = 1; } while(n > 0){ if(n & 1) B = mul(B, A); A = mul(A, A); n >>= 1; } return B; } int main() { int t; scanf("%d", &t); while(t--){ long long n; scanf("%lld", &n); mat A(3, vec(3)); A[0][0] = 1; A[0][1] = 0; A[0][2] = 1; A[1][0] = 1; A[1][1] = 0; A[1][2] = 0; A[2][0] = 0; A[2][1] = 1; A[2][2] = 0; A = pow(A, n - 2); ll ans = (A[2][0] * 6 + A[2][1] * 4 + A[2][2] * 3) % mod; printf("%lld\n", ans); } return 0; }