P1357 花园

【数据规模】

40%的数据中,N<=20;

60%的数据中,M=2;

80%的数据中,N<=10^5。

100%的数据中,N<=10^15。

看到这个数据范围,我首先想到的是80分的写法

80分的写法可以使用状压DP

f[i][j]表示第i位,前m个二进制状态为j有多少种方式

t1=(j>>1)|(1<<(m-1));

t2=j>>1;

转移到下一位有两种选择

t1为选C花圃,t2为选P花圃

当然如果选t1则超过k个C花圃,则不可转移

if(ji[t1]<=k) f[i+1][t1]=(f[i+1][t1]+f[i][j])%mo;
f[i+1][t2]=(f[i+1][t2]+f[i][j])%mo;

另外要注意的是原花圃是一个环

所以我们枚举起始状态,转移n+m次,取f[n+m]中状态与起始相同加入总和

80分的状压DP具体实现如下:

#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long ll;
inline ll read()
{
    register ll p(1),a(0);register char ch=getchar();
    while((ch<‘0‘||ch>‘9‘)&&ch!=‘-‘) ch=getchar();
    if(ch==‘-‘) p=-1,ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘) a=a*10+ch-48,ch=getchar();
    return a*p;
}
const ll N=100100,M=(1<<5),mo=1000000007;
ll f[N][M],n;
int ans=0,ji[M],t1,t2,m,k;
inline int suan(int xx)
{
    register int num=0;
    while(xx)
    {
        if(xx&1) num++;
        xx>>=1;
    }
    return num;
}
int main()
{
    // freopen("input","r",stdin);
    // freopen("output","w",stdout);
    n=read(),m=read(),k=read();
    for(register int i=(1<<m)-1;i>=0;i--)
        ji[i]=suan(i);
    for(register int kk=(1<<m)-1;kk>=0;kk--) if(ji[kk]<=k)
    {
        memset(f,0,sizeof(f));
        f[m][kk]=1;
        for(register int i=m;i<  n+m;i++)
            for(register int j=(1<<m)-1;j>=0;j--)
            {
                t1=(j>>1)|(1<<(m-1));
                t2=j>>1;
                // prllf("%d %d\n",t1,t2);
                if(ji[t1]<=k) f[i+1][t1]=(f[i+1][t1]+f[i][j])%mo;
                f[i+1][t2]=(f[i+1][t2]+f[i][j])%mo;
            }
        ans=(ans+f[n+m][kk])%mo;
    }
    printf("%d",ans);
    return 0;
}

然后我们再来考虑100分的做法

范围开到了1e15我们显然只能使用logn的算法

很容易想到矩阵快速幂的套路

使用状压DP的2^m种状态作为点

于是可以使用原来的思路建出一步可达矩阵图

快速幂n次方即可

100分矩阵快速幂实现如下:

#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long ll;
inline ll read()
{
    register ll p(1),a(0);register char ch=getchar();
    while((ch<‘0‘||ch>‘9‘)&&ch!=‘-‘) ch=getchar();
    if(ch==‘-‘) p=-1,ch=getchar();
    while(ch>=‘0‘&&ch<=‘9‘) a=a*10+ch-48,ch=getchar();
    return a*p;
}
const ll N=100100,M=(1<<5),mo=1000000007;
struct matrix
{
    ll data[M][M];
    matrix(){memset(data,0,sizeof(data));}
};
ll f[N][M],n,ans=0,ji[M],t1,t2,m,k,big;
inline int suan(int xx)
{
    register int num=0;
    while(xx)
    {
        if(xx&1) num++;
        xx>>=1;
    }
    return num;
}
matrix chen(matrix a,matrix b)
{
    matrix c;
    for(register int i=0;i<big;i++)
        for(register int j=0;j<big;j++) if(a.data[i][j])
            for(register int k=0;k<big;k++)
                c.data[i][k]=(c.data[i][k]+a.data[i][j]*b.data[j][k])%mo;
    return c;
}
matrix qs(matrix a,ll b)
{
    matrix ans;
    for(register int i=0;i<big;i++) ans.data[i][i]=1;
    while(b)
    {
        if(b&1) ans=chen(ans,a);
        a=chen(a,a);
        b>>=1;
    }
    return ans;
}
int main()
{
    // freopen("input","r",stdin);
    // freopen("output","w",stdout);
    n=read(),m=read(),k=read();
    matrix temp,now;
    big=1<<m;
    for(register int i=(1<<m)-1;i>=0;i--)
        ji[i]=suan(i);
    for(register int i=(1<<m)-1;i>=0;i--) if(ji[i]<=k)
    {
        t1=(i>>1)|(1<<(m-1));
        t2=i>>1;
        if(ji[t1]<=k) temp.data[i][t1]=1;
        temp.data[i][t2]=1;
    }
    temp=qs(temp,n);
    for(register int i=(1<<m)-1;i>=0;i--) if(ji[i]<=k)
        ans=(ans+temp.data[i][i])%mo;
    printf("%lld",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/cold-cold/p/10134857.html

时间: 2024-10-20 01:05:08

P1357 花园的相关文章

luogu P1357 花园

题目链接 luogu P1357 花园 题解 开始读错题了,QAq,只看了m<=n,然后这怎je做啊QAq 用一种可行状态做环的起始部分,维护后m个的状态,进行装压dp,在后边插可行状态,那么如何保证环呢 , 由于是环,所以转移n次后,贡献有用的方案是,末装态与原来相同的方案 ,(也就是末状态转移为初状态的方案) 当然,状态必须在满足条件的状态中转移 ->80pts 对于转移矩阵,矩阵快速幂优化装态转移的递推 ->100pts 那么状态S答案为矩阵[S][S]的值 代码 #include

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 由于请

【题解】Luogu P1357 花园

原题传送门 我们先将花圃断环为链,并将\([1,m]\)复制一份到\([n+1,n+m]\),最后要求\([1,n+m]\)是合法序列且\([1,m]\)与\([n+1,n+m]\)相等的序列的数量即可 \(m\)很小,珂以考虑状压,\(C\)是\(0\),\(P\)是\(1\),可以将长\(m\)的花圃压缩成一个数 我们先考虑\([1,m]\)的可行方法,直接暴力预处理 如何从\([1,m]\)转移到\([2,m+1]\):设\([1,m]\)的状态为\(a\),我们珂以将第一个数字删掉再在最

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,

洛谷教主花园dp

洛谷-教主的花园-动态规划 题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值. 教主最喜欢3种树,这3种树的高度分别为10,20,30.教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高. 输入输出格式 输入格式: 输入文件garden.in的第1行为一个正整数n,表示需要种的

洛谷-教主的花园-动态规划

题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值. 教主最喜欢3种树,这3种树的高度分别为10,20,30.教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高. 输入输出格式 输入格式: 输入文件garden.in的第1行为一个正整数n,表示需要种的树的棵树. 接下来n行,每行

P1133 教主的花园

P1133 教主的花园 题目描述 教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值. 教主最喜欢3种树,这3种树的高度分别为10,20,30.教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高. 输入输出格式 输入格式: 输入文件garden.in的第1行为一个正整数n,表示需要种的树的

福建省历届夏令营 花园

题目描述 小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 由

二分+最短路判定 BZOJ 2709: [Violet 1]迷宫花园

BZOJ 2709: [Violet 1]迷宫花园 Sample Input 5 10.28 9 9 ######### # # # # # # # #S# # ##### # # ## # # # ### ### ##E # ######### 4.67 9 9 ######### # ## ## ### #S# # # # E ## # # ##### # ## ### # ##### # # # # ######### 39.06 9 9 ######### # # # # # # # #