【矩阵快速幂】NC17890-方格填色
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
给一个的方格,Applese想要给方格填上颜色,每个格子可以是黑色或者白色。他要求左右相邻两格不能同为白色且相邻两列不能全为黑色。
求满足条件的方案数。
输入描述:
输入两个整数m, n。(1 ≤ m ≤ 5, 1 ≤ n ≤ 1e18)。
输出描述:
输出答案对1e9 + 7取模的结果。
示例1
输入
3 1
输出
8
示例2
输入
3 5
输出
1640
示例3
输入
5 5
输出
351032
思路
题意如题不用解读
因为很小,我们可以考虑一列一列的去看,每个格子是黑色或者白色,那么每一列最多能有个方案数,我们可以用一个动态规划来求方案数
设是一个到的一个数,看成是位的二进制,表示涂色状态,0是白色,1是黑色
特别大,这个状态是可以递推的,但不能用线性,这个时候可以使用一种常用的优化线性递推的数论知识,矩阵快速幂
那么可以设,来构造一个转移矩阵,题目需要满足一些条件,没有相邻的两列中两个相邻的格为白色并且没有相邻两列全黑。
容易知道可以用限制条件来得到第一个条件的可行方案,并且不能同为来得到第二个条件的可行方案,设转移矩阵为,那么在两格条件都满足时为1,否则为0,一直往下递推可以知道:
最终答案为
矩阵快速幂复杂度
(就写出了两个板子题把自己高兴坏了,不知道在高兴什么)
AC代码
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define int long long
#define ull unsigned long long
#define PII pair<int,int>
#define endl '\n'
const int N = 40;
const int mod = 1e9 + 7;
const double pi = acos(-1.0);
typedef long long ll;
int t, n, m, M;
struct Matrix {//矩阵初始化,乘法重载
int a[N][N];//2^5只有32,开40*40足够
Matrix()
{
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
a[i][j] = 0;
}
}
}
Matrix operator * (const Matrix& Ma_) const
{
Matrix res;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < m; ++j) {
for (int k = 0; k < m; ++k) {
res.a[i][j] = (res.a[i][j] + a[i][k] * Ma_.a[k][j] % mod) % mod;
}
}
}
return res;
}
};
Matrix quickpow(Matrix res,Matrix sta, ll b)//快速幂板子
{
while (b > 0)
{
if (b & 1) res = res * sta;
sta = sta * sta;
b >>= 1;
}
return res;
}
void solve()
{
m = (1 << M);
Matrix state;
Matrix trans;
for (int i = 0; i < m; i++) {
state.a[i][i] = 1;
}
for (int i = 0; i < m; i ++) {
for (int j = 0; j < m; j ++) {
if ((i | j)) {
int flag = 0;
for (int k = 0; k <= M; k ++) {
if (((1 << k) & i) & ((1 << k) & j)) {
flag = 1;
break;
}
}
if (flag == 1)continue;
trans.a[i][j] = 1;
}
}
}//根据条件构造转移矩阵
state = quickpow(state, trans, (n - 1));//快速幂
int ans = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
ans = (ans + state.a[i][j] + mod) % mod;
}
}
cout << (ans + mod) % mod << endl;//方案数累加输出,注意取模
return;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
while (cin >> M >> n) {
solve();
}
return 0;
}
分类:
蒟蒻の解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用