核💗: 对状态转移矩阵的理解---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来说,实在是太难了。快帮他算算什么时候应该拍手吧。