HDU5863cjj's string game(DP+矩阵快速幂)

题意:

让你用k个字母构造出两个长度为n的a,b串,其中a,b连续对应子串的长度不能超过m,问方案数。


分析:

dp[i][j]表示现在构造了i长度,长度j后缀连续对应相等,那么dp[i][j] = dp[i-1][j-1]*k,特别地,dp[i][0] = sigma(dp[i-1][j]*(k-1)*k) (0=<j<=m).


令sum=dp[n][0]+dp[n][1]…+dp[n][m],那么sum的意义可以解释为前面出现的最长匹配<=m的方案,最后出现的最长匹配<=m的方案,而我们要求的是前面出现的最长匹配<=m,最后出现的最长匹配<=m,且两个等号至少一个成立的方案,那么去掉不合法的即可,不合法方案即为前面出现的最长匹配<=m-1的方案,最后出现的最长匹配<=m-1的方案,这就是将原来dp转移转移过程中的m变成m-1后的子问题,故做两遍矩阵快速幂,将sum值做差即为答案 。


PS:有点容斥的意思,但是没想到可以这样来计算出答案。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define mod 1000000007
int n, k;
struct Matrix
{
    int r, c;
    LL mat[13][13];
    void init()
    {
        memset(mat, 0, sizeof(mat));
    }
}ans;
Matrix mul(Matrix a, Matrix b)
{
    Matrix ret;
    ret.r=a.r;
    ret.c=b.c;
    for(int i=1; i<=ret.r; i++)
    {
        for(int j=1; j<=ret.c; j++)
        {
            ret.mat[i][j]=0;
            for(int k=1; k<=a.c; k++)
            {
                ret.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
                ret.mat[i][j]%=mod;
            }
        }
    }
    return ret;
}
Matrix quick_pow(Matrix a, int b)
{
    int m=a.r;
    Matrix ret;
    ret.r=ret.c=m+1;
    ret.init();
    for(int i=1; i<=m+1; i++)
        ret.mat[i][i]=1;
    while(b)
    {
        if(b&1)
            ret = mul(ret, a);
        a = mul(a, a);
        b >>= 1;
    }
    return ret;
}
LL solve(int m)
{
    LL ans=0;
    Matrix dp;
    dp.init();
    dp.r=m+1;dp.c=m+1;
    for(int i=1; i<=m; i++)
        dp.mat[i+1][i]=k;
    for(int i=1; i<=m+1; i++)
        dp.mat[i][m+1]=k*(k-1);
    dp=quick_pow(dp, n);
    for(int i = 1;i <= m+1;i++)
        ans=(ans + dp.mat[m+1][i]) % mod;
    return ans;
}
int t, m;
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>k;
        LL ans=(solve(m)-solve(m-1)+mod)%mod;
        cout<<ans<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值