zoukankan      html  css  js  c++  java
  • Codeforces 176B 经典DP

    非常好的一个题目,CF上的DP都比较经典

    题意就是 给定一个串A,B,正好执行K次操作,每次操作可以把 A串从中间切开,并调换两部分的位置,问最后得到B串共有多少种不同的切法(只要中间有一次不同,即视为不同)

    首先,题目的一个关键点一定要抓到,就是 ,不管怎么切 然后调换位置,其实串根本没变,你把串想成一个环,从某一点分成两部分并且交换位置,其实就是把串的起点变到了该点,这是很关键也是最机智的一点

    然后,我们要发现规律,你纸上模拟也行,推理也行。。

    我们发现:1.首先原串(即以0号字母开头的)个数为1,其他种类串为0。

                  2.第一次变化之后,原串个数即为0,其他串个数为1(由原串变过去,但原串变不成自己)

                  3.第二次变化,原串个数为len-1(由其他串变过来),其他串变为len-2 (由原串 和 除自己外的其他串变过来, 0+len-2,原串为0,故为len-2)

    所以我们总结出的规律,假设 dp[i][0]为原串,dp[i][1]为其他串

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

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

    即由上一次的原串 和 其他串的个数,可推得现在的原串和其他串的个数,所以dp的第一维也只要开2就行,用滚动数组

    最后枚举一下,B串跟A串 有多少种原串和其他串(其实就是枚举开始的点) 乘以对应的dp即可

    真的是巨经典的一个相当于计数dp的题目

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL __int64
    using namespace std;
    const LL M=1000000000+7;
    LL dp[2][2];
    char s1[1010],s2[1010];
    int k;
    int main()
    {
        while (scanf("%s%s%d",s1,s2,&k)!=EOF)
        {
            int len=strlen(s1);
            dp[0][0]=1;
            dp[0][1]=dp[1][1]=dp[1][0]=0;
            int p=0;
            while (k--)
            {
                dp[p^1][0]=(len-1)*dp[p][1];
                dp[p^1][1]=dp[p][0]+dp[p][1]*(len-2);
                p^=1;
                if (dp[p][0]>=M) dp[p][0]%=M;
                if (dp[p][1]>=M) dp[p][1]%=M;
            }
            LL ans=0;
            for (int i=0;i<len;i++){
                bool flag=1;
                for(int j=0;j<len;j++){
                    int q=i+j;
                    q%=len;
                    if (s1[q]!=s2[j]){
                        flag=0;
                        break;
                    }
                }
                if (flag){
                    if (i==0) ans+=dp[p][0];
                    else ans+=dp[p][1];
                    if (ans>=M) ans%=M;
                }
            }
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    asm
    chrome-vimium在markdown插件的页面失去效果
    chrome-如何给simple world highlighter添加开关
    调整Chrome中文字体为雅黑
    最新版本的Chrome浏览器如何设置网页编码?
    访问sharepoint站点自动使用当前用户名和密码登录
    请停用以开发者模式运行的扩展
    ARM Instruction Set
    阿里前端面试
    原型链
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3902862.html
Copyright © 2011-2022 走看看