codeforces 176B Word Cut (计数dp)

题意:

给出一个串,可以从任意地方截取,然后把两部分位置换下得到新的串,问从a串变到b串有多少种方法。

题解:

首先我们分析这种变换产生的结果,发现无论怎么变换一个串只能变成和自己不同的len-1个串,而且之后的变化不会出现新的串。这个结论是关键。

然后我们分析下,有原串可以变成len-1个非原串,每个非原串又可以变成1个原串,和len-2个非原串。那么我们方向来分析下,一个原串是可以由len-1个非原串变来,一个非原串可以有len-2个非原串变来。

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

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

dp[i][0]表示用了i步变成原串的个数,dp[i][1]表示用了i步变成非原串的个数。


#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<map>
using namespace std;
typedef long long lld;
const int oo=0x3f3f3f3f;
const lld OO=1LL<<61;
const lld MOD=1000000007;
#define eps 1e-6
#define maxn 100005
lld dp[2][2];
char st[2005],se[1005];

int main()
{
    int n;
    while(scanf("%s%s",st,se)!=EOF)
    {
        scanf("%d",&n);
        int len=strlen(st);
        for(int i=0;i<len;i++)
        {
            st[i+len]=st[i];
        }
        dp[0][0]=1;
        dp[0][1]=0;
        int cur=1;
        for(int i=1;i<=n;i++,cur^=1)
        {
            dp[cur][0]=((len-1)*dp[cur^1][1]+MOD)%MOD;
            dp[cur][1]=(dp[cur^1][0]+(len-2)*dp[cur^1][1]+MOD)%MOD;
        }
        cur^=1;
        lld ans=0;
        for(int i=0;i<len;i++)
        {
            int pos=i;
            for(int j=0,k=i;j<len;k++,j++)
            {
                if(st[k]!=se[j])
                {
                    pos=-1;
                    break;
                }
            }
            if(pos!=-1)
            {
                if(pos==0)
                    ans=(ans+dp[cur][0]+MOD)%MOD;
                else
                    ans=(ans+dp[cur][1]+MOD)%MOD;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
/**
ab
ab
2
ababab
ababab
1
ab
ba
2

*/





你可能感兴趣的:(codeforces 176B Word Cut (计数dp))