P1357 花园 (矩阵快速幂+ DP)
Posted lwqq3
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1357 花园 (矩阵快速幂+ DP)相关的知识,希望对你有一定的参考价值。
题意:一个只含字母C和P的环形串
求长度为n且每m个连续字符不含有超过k个C的方案数
m <= 5 n <= 1e15
题解:用一个m位二进制表示状态 转移很好想
但是这个题是用矩阵快速幂加速dp的 因为每一位的转移都是一样的
用一个矩阵表示状态i能否转移到状态j 然后跑一遍
初试模板题
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod = 1e9 + 7; ll n, m, k, len; struct node ll c[64][64]; re, x; bool check(int x) int cnt = 0; while(x) if(x & 1) cnt++; x >>= 1; if(cnt > k) return false; return true; node mul(node a, node b) node res; memset(res.c, 0, sizeof(res.c)); for(int i = 0; i < len; i++) for(int j = 0; j < len; j++) for(int k = 0; k < len; k++) res.c[i][j] = (res.c[i][j] + a.c[i][k] * b.c[k][j] % mod) % mod; return res; node pow_mod(node x, ll y) node res; for(int i = 0; i < len; i++) res.c[i][i] = 1; while(y) if(y & 1) res = mul(res, x); x = mul(x, x); y >>= 1; return res; int main() scanf("%lld%lld%lld", &n, &m, &k); len = (1 << m); for(int i = 0; i < len; i++) for(int j = 0; j < len; j++) x.c[i][j] = 0; for(int i = 0; i < len; i++) if(!check(i)) continue; int tmp = i; int ctmp = 1 << (m - 1); if((tmp & ctmp) == ctmp) tmp -= ctmp; tmp <<= 1; if(check(tmp)) x.c[i][tmp] = 1; tmp |= 1; if(check(tmp)) x.c[i][tmp] = 1; re = pow_mod(x, n); ll ans = 0; for(int i = 0; i < len; i++) if(check(i)) ans += re.c[i][i]; ans %= mod; printf("%lld\n", ans); return 0;
以上是关于P1357 花园 (矩阵快速幂+ DP)的主要内容,如果未能解决你的问题,请参考以下文章