牛客練習賽27 計數
阿新 • • 發佈:2019-02-13
題意:
n個數字一個環,每個數字只能是3或7,要求所有相鄰的m個數中,7的個數大於等於3的個數,求方案數。
題解:
由於m<=5,用一個數字表示最後m個數的狀態,轉移方程很好寫:
dp[i]->dp[j](j和i都合法,並且二進位制下i的後m-1位和j的前m-1位相同)
然後構造轉移矩陣,求快速冪
如何保證是環的情況下依據合法?
我們列舉初始狀態,2^m種,然後計數時只統計最後狀態和初始狀態合法的。
教訓:
位運算中 & 和 << 不是一個優先順序!!
程式碼:
#include<bits/stdc++.h> #define N 32 #define INF 0x3f3f3f3f #define eps 1e-10 #define pi 3.141592653589793 #define mod 998244353 #define LL long long #define pb push_back #define cl clear #define si size #define lb lower_bound #define mem(x) memset(x,0,sizeof x) #define sc(x) scanf("%d",&x) #define scc(x,y) scanf("%d%d",&x,&y) #define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z) using namespace std; LL n,m,lim; bool check(int x) { return __builtin_popcount(x)>=(m+1)/2; } struct Matrix { LL a[N][N]; Matrix(){memset(this,0,sizeof(Matrix));} Matrix operator *(const Matrix x) const { Matrix ans; for(int i=0;i<lim;i++) if (check(i)) for(int j=0;j<lim;j++) if (check(j)) { for(int k=0;k<lim;k++) ans.a[i][j]+=a[i][k]*x.a[k][j]%mod; ans.a[i][j]%=mod; } return ans; } friend Matrix operator ^(Matrix x,LL y) { Matrix ans; for(int i=0;i<lim;i++) ans.a[i][i]=1; while(y) { if (y&1) ans=ans*x; x=x*x; y>>=1; } return ans; } }x; int main() { LL ans=0; cin>>n>>m; lim=1<<m; for (int i=0;i<lim;i++) for (int j=0;j<lim;j++) if (check(j) && check(i) && ( j&((1<<m-1)-1))==(i>>1) ) x.a[j][i]=1; Matrix f=x^(n-m); for (int i=0;i<lim;i++) { for (int j=0;j<lim;j++) { int fg=1; for (int k=1;k<m;k++) if (check(((j<<k)|(i>>m-k))&lim-1)) fg++; if (fg==m) ans=(ans+f.a[i][j])%mod; } } cout<<ans; }