Codeforces 176B【计数DP】

本文介绍一种使用计数动态规划方法解决特定字符串转换问题的思路与实现过程。通过构建DP数组,记录每一步变成目标字符串的方案数,最终求得原字符串经过指定次数操作变为另一字符串的方法数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

给你两个串s1,s2和一个K,
有一种操作是在一个串切开然后交换位置,
问s1有多少种方法经过K次这样的操作变成s2;

思路:

(从来没接触过计数DP...还是太菜...参考了【大牛blog

首先呢,不管怎么切怎么换,都是原串自己转来转去有没有???看到这个其实我还是不懂。。。。

然后呢,我们搞一个DP数组记下数,纯粹就是计数的;


dp[now][0]代表到第i步变成原串的方案数;

dp[now][1]代表到第i步变成非原串的方案数;

从哪里变成原串啊?一个原串可以变成len-1个非原串,那么len-1个非原串也能变成1个原串咯

从哪里变成非原串?本来原串能变成len-1个非原串,而每个非原串又能变成1个原串,还能变成len-2个跟他也不同的串;

so...

dp[now][0]=dp[last][1]*(len-1);

dp[now][1]=dp[last][0]+dp[last][1]*(len-2);

最后只要枚举一下环,有没有哪个位置开始起和目标串一样,然后加上方案就好了;

牛逼啊;

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int>PII;
const double eps=1e-5;
const double pi=acos(-1.0);
const int INF=0x3f3f3f3f;

const int mod=1e9+7;
const int N=1e3+10;
char s1[N],s2[N];
int k;

LL dp[2][2];

int main()
{
    int len;
    scanf("%s%s%d",s1,s2,&k);
    len=strlen(s1);
    for(int i=0;i<len;i++)
        s1[i+len]=s1[i];

    int now=0;
    dp[now][0]=1;
    dp[now][1]=0;

    for(int i=1;i<=k;i++)
    {
        now=1-now;
        dp[now][0]=(len-1)*dp[1-now][1]%mod;
        dp[now][1]=(dp[1-now][0]+dp[1-now][1]*(len-2)%mod)%mod;
    }

   //printf("%lld %lld\n",dp[now][0],dp[now][1]);

    LL ans=0;
    for(int i=0;i<len;i++)
    {
        int pos=i;
        for(int j=0,t=i;j<len;t++,j++)
        {
            if(s1[t]!=s2[j])
            {
                pos=-1;
                break;
            }
        }
        if(pos!=-1)
        {
            if(pos==0)
                ans=(ans+dp[now][0])%mod;
            else
                ans=(ans+dp[now][1])%mod;
        }
    }
    printf("%lld\n",ans);
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值