P1357 花园 (矩阵快速幂+ DP)
生活随笔
收集整理的這篇文章主要介紹了
P1357 花园 (矩阵快速幂+ DP)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題意:一個只含字母C和P的環(huán)形串
求長度為n且每m個連續(xù)字符不含有超過k個C的方案數(shù)?
m <= 5? n <= 1e15
題解:用一個m位二進(jìn)制表示狀態(tài) 轉(zhuǎn)移很好想
但是這個題是用矩陣快速冪加速dp的 因?yàn)槊恳晃坏霓D(zhuǎn)移都是一樣的
用一個矩陣表示狀態(tài)i能否轉(zhuǎn)移到狀態(tài)j 然后跑一遍
統(tǒng)計答案特別講究 因?yàn)槭且粋€環(huán) 從1 ~ n+m
那么 m+1 ~ n + m之間就是我們所求的 1 ~ m和n+1 ~ n + m是同樣的一段
就相當(dāng)于把m位二進(jìn)制狀態(tài) 轉(zhuǎn)移n次
然后再轉(zhuǎn)移到自己的就是答案
初試模板題
?
#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; } View Code?
轉(zhuǎn)載于:https://www.cnblogs.com/lwqq3/p/11080597.html
總結(jié)
以上是生活随笔為你收集整理的P1357 花园 (矩阵快速幂+ DP)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java获取文件名方法,利用Java获取
- 下一篇: Element.shadowRoot