有關狀態轉移矩陣的兩道題目


核💗: 對狀態轉移矩陣的理解---A(x,y) 從x狀態轉移y狀態有多少種可能; B=A^n----B(x,y)表示經過n輪轉移之后從x到y有多少轉換方式

NO.1---方格填數

鏈接:https://ac.nowcoder.com/acm/contest/190/J
來源:牛客網

題目描述

 

給一個m x n的方格,Applese想要給方格填上顏色,每個格子可以是黑色或者白色。他要求左右相鄰兩格不能同為白色且相鄰兩列不能全為黑色。

求滿足條件的方案數。

輸入描述:

輸入兩個整數m, n。(1 ≤ m ≤ 5, 1 ≤ n ≤ 10
18
)。

輸出描述:

輸出答案對10
9
 + 7取模的結果。
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const LL mod=1e9+7;
 5 int tot;
 6 struct mat {
 7     LL m[50][50];
 8     mat operator*(const mat& t) const {
 9         mat ans;
10         for (int i=0;i<tot;i++)
11             for (int j=0;j<tot;j++) {
12                 LL x=0;
13                 for (int k=0;k<tot;k++)
14                     x=( m[i][k]*t.m[k][j]%mod+x )%mod;
15                 ans.m[i][j]=x;
16             }
17         return ans;
18     }
19 };
20 mat A;
21 int m;LL n;
22 mat q_pow (mat X,LL k) {
23     mat B;
24     for (int i=0;i<tot;i++) B.m[i][i]=1;
25     while (k) {
26         if (k&1) B=B*X;
27         X=X*X;
28         k=(k>>1);
29     }
30     return B;
31 }
32 int main ()
33 {
34     scanf ("%d %lld",&m,&n);
35     tot=(1<<m);
36     for (int i=0;i<tot;i++)
37         for (int j=0;j<tot;j++) {
38             if (i==0&&j==0) continue;
39             if (!(i&j)) A.m[i][j]=1;
40         }
41     A=q_pow (A,n-1);
42     LL sum=0;
43     for (int i=0;i<tot;i++)
44         for (int j=0;j<tot;j++)
45             sum=(sum+A.m[i][j])%mod;
46     printf("%lld\n",sum);
47     return 0;
48 }

NO.2--方格填數

鏈接:https://ac.nowcoder.com/acm/contest/188/F
來源:牛客網

小w喜歡Van數列 
小w有一個長度為n的由3和7構成的環狀序列
小w規定序列中任意相鄰的m個數,3的個數不能超過7的個數 
小w想知道這樣的序列共有多少種 ,方案數對於998244353取mod

 

輸入描述:

 

一行兩個數n,m

 

輸出描述:

 

一個數表示對998244353取模后的方案數
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const LL mod=998244353;
 5 LL n,m,dim;
 6 bool check (int x) {
 7     int tmp=x,sum=0;
 8     while (tmp) {
 9         if (tmp&1) sum++;
10         tmp=tmp>>1;
11     }
12     return sum>=(m+1)/2;
13 }
14 struct matrix {
15     LL a[40][40];
16     friend matrix operator*(const matrix& x,const matrix& y) {
17         matrix ans;
18         for (int i=0;i<dim;i++)
19             if (check(i))
20                 for (int j=0;j<dim;j++)
21                     if (check(j)) {    
22                         ans.a[i][j]=0;
23                         for (int k=0;k<dim;k++) 
24                             ans.a[i][j]=(ans.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
25                     }
26         return ans;
27     }
28 };    
29 matrix q_pow (matrix x,LL k) {
30     matrix ans; 
31     for (int i=0;i<dim;i++)
32         for (int j=0;j<dim;j++)
33             if (i==j) ans.a[i][j]=1;
34             else      ans.a[i][j]=0;
35     while (k) {
36         if (k&1)  ans=ans*x;
37         x=x*x;
38         k=k>>1;
39     }
40     return ans;
41 }
42 matrix tra;
43 int main ()
44 {
45     scanf ("%lld %lld",&n,&m);
46     dim=(1<<m); 
47     for (int i=0;i<dim;i++)// 狀態描述: dp[i] :最后m位狀態是i的種類有多少種
48         for (int j=0;j<dim;j++)
49             if (check(i)&&check(j)&&(i&(1<<m-1)-1)==(j>>1)) {
50                 tra.a[i][j]=1;
51                 //cout<<i<<" "<<j<<" :"<<tra.a[i][j]<<endl;
52             }
53     matrix ans=q_pow (tra,n-m);
54     LL sum=0;
55     for (int i=0;i<dim;i++) if (check(i))  //最后枚舉初始狀態和最終狀態是否兼容
56         for (int j=0;j<dim;j++) if (check(j)) {
57             int flag=1;
58             for (int k=1;k<m;k++)  
59                 if ( check ( ( ((j<<k)|(i>>m-k)) )&(dim-1) ) ) flag++;
60             if (flag==m) sum=(sum+ans.a[i][j])%mod;
61         }
62     printf("%lld\n",sum);
63     return 0;
64 }

 

 

 

鏈接:https://ac.nowcoder.com/acm/contest/190/D
來源:牛客網

今天是個特殊的日子,CSL和他的小伙伴們圍坐在一張桌子上玩起了明七暗七的游戲。游戲規則是這樣的:

一個人報出一個起始數,接下來按照逆時針的順序輪流報數,如果碰到數是7的倍數或含有7,則拍手,下一個人接着報數。直到有一個人報錯了數字或者沒有及時拍手為止。

玩游戲嘛,當然得有懲罰。這么簡單的游戲對CSL的學霸小伙伴而言實在是太無腦了,輕輕松松數到上萬根本不在話下。但是對於數學是體育老師教的CSL來說,實在是太難了。快幫他算算什么時候應該拍手吧。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM