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;
}

原文地址:https://www.cnblogs.com/lwqq3/p/11080597.html

时间: 2024-11-08 05:39:08

P1357 花园 (矩阵快速幂+ DP)的相关文章

bnu 34985 Elegant String(矩阵快速幂+dp推导公式)

Elegant String Time Limit: 1000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main Prev Submit Status Statistics Discuss Next Type: None None Graph Theory      2-SAT     Articulation/Bridge/Biconnected Component      Cy

VOJ 1067 Warcraft III 守望者的烦恼 (矩阵快速幂+dp)

题目链接 显然可知 dp[n] = dp[n-k] + dp[n-k+1] + ... +dp[n-1]; 然后要用矩阵来优化后面的状态转移. 也就是矩阵 0 1 0 0    a     b 0 0 1 0 * b =  c 0 0 0 1    c     d 1 1 1 1    d    a+b+c+d 然后跑快速幂 #include <iostream> #include <cstdio> #include <algorithm> #include <c

COJ 1208 矩阵快速幂DP

题目大意: f(i) 是一个斐波那契数列 , 求sum(f(i)^k)的总和 由于n极大,所以考虑矩阵快速幂加速 我们要求解最后的sum[n] 首先我们需要思考 sum[n] = sum[n-1] + f(i+1)^k 那么很显然sum[n-1]是矩阵中的一个元素块 那么f(i+1)^k怎么利用f(i) , f(i-1)来求 f(i+1)^k = (f(i) + f(i-1)) ^ k 假如k = 1 , 可以看出f(i+1) = f(i-1) + f(i) (1,1) k = 2 , 可以看出

Codeforces 576D Flights for Regular Customers 矩阵快速幂+DP

题意: 给一个\(n\)点\(m\)边的连通图 每个边有一个权值\(d\) 当且仅当当前走过的步数\(\ge d\)时 才可以走这条边 问从节点\(1\)到节点\(n\)的最短路 好神的一道题 直接写做法喽 首先我们对边按\(d_i\)由小到大排序 设\(f_i\)表示加上\(1\sim i-1\)的所有边走\(d_i\)次后各点间的联通情况 \(G\)表示只连\(1\sim i-1\)的边的邻接矩阵 这些我们可以用一个\(01\)邻接矩阵来存储 则有 \(f_i=f_{i-1}*G^{d_i-

P1357 花园 状压 矩阵快速幂

题意 小L有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为1~N(2<=N<=10^15).他的环形花园每天都会换一个新花样,但他的花园都不外乎一个规则,任意相邻M(2<=M<=5,M<=N)个花圃中有不超过K(1<=K<M)个C形的花圃,其余花圃均为P形的花圃. 例如,N=10,M=5,K=3.则 CCPCPPPPCC 是一种不符合规则的花圃: CCPPPPCPCP 是一种符合规则的花圃. 请帮小L求出符合规则的花园种数Mod 1000000007 由于请

Codeforces Round #291 (Div. 2) E - Darth Vader and Tree (DP+矩阵快速幂)

这题想了好长时间,果断没思路..于是搜了一下题解.一看题解上的"快速幂"这俩字,不对..这仨字..犹如醍醐灌顶啊...因为x的范围是10^9,所以当时想的时候果断把dp递推这一方法抛弃了.我怎么就没想到矩阵快速幂呢.......还是太弱了..sad..100*100*100*log(10^9)的复杂度刚刚好. 于是,想到了矩阵快速幂后,一切就变得简单了.就可以把距离<=x的所有距离的点数都通过DP推出来,然后一个快速幂就解决了. 首先DP递推式很容易想到.递推代码如下: for(

hdu 2604 Queuing dp找规律 然后矩阵快速幂。坑!!

http://acm.hdu.edu.cn/showproblem.php?pid=2604 这题居然O(9 * L)的dp过不了,TLE,  更重要的是找出规律后,O(n)递推也过不了,TLE,一定要矩阵快速幂.然后立马GG. 用2代表m,1代表f.设dp[i][j][k]表示,在第i位,上一位站了的人是j,这一位站的人是k,的合法情况. 递推过去就是,如果j是1,k是2,那么这一位就只能放一个2,这个时猴dp[i][k][2] += dp[i - 1][j][k]; 其他情况分类下就好,然后

瓷砖铺放 (状压DP+矩阵快速幂)

未加矩阵快速幂 50分 1 const dx:array[1..8,1..3] of longint= 2 ((-1,0,0),(-1,0,0),(1,0,0),(0,1,0),(-1,0,0),(-1,1,0),(0,1,0),(-1,0,1)); 3 dy:array[1..8,1..3] of longint= 4 ((0,1,0),(0,-1,0),(0,-1,0),(1,0,0),(0,1,-1),(0,0,-1),(1,0,-1),(0,1,0)); 5 mo=65521; 6 va

HUST 1569(Burnside定理+容斥+数位dp+矩阵快速幂)

传送门:Gift 题意:由n(n<=1e9)个珍珠构成的项链,珍珠包含幸运数字(有且仅由4或7组成),取区间[L,R]内的数字,相邻的数字不能相同,且旋转得到的相同的数列为一种,为最终能构成多少种项链. 分析:这是我做过的最为综合的一道题目(太渣了),首先数位dp筛选出区间[L,R]内的幸运数字总数,dp[pos]表示非限制条件下还有pos位含有的幸运数字个数,然后记忆化搜索一下,随便乱搞的(直接dfs不知会不会超时,本人做法900+ms险过,应该直接dfs会超时),再不考虑旋转相同的情况,可以