zoukankan      html  css  js  c++  java
  • ZOJ 3791 An Easy Game[dp]

    One day, Edward and Flandre play a game. Flandre will show two 01-strings s1 and s2, the lengths of two strings are n. Then, Edward must move exact k steps. In each step, Edward should change exact m positions of s1. That means exact m positions of s1, '0' will be changed to '1' and '1' will be changed to '0'.

    The problem comes, how many different ways can Edward change s1 to s2 after k steps? Please calculate the number of the ways mod 1000000009.

    Input

    Input will consist of multiple test cases and each case will consist of three lines. The first line of each case consist of three integers n (1 ≤ n ≤ 100), k (0 ≤ k ≤ 100), m (0 ≤ mn). The second line of each case is a 01-string s1. The third line of each case is a 01-string s2.

    Output

    For each test case, you should output a line consist of the result.

    Sample Input

    3 2 1
    100
    001
    

    Sample Output

    2
    

    Hint

    100->101->001
    100->000->001
    

    题意:给两个01串A和B,长度都是n。共进行k次操作,每次需翻转m个位,问有多少种方法将A转换成B。


    两个串哪位是1哪位是0是无关紧要的,因为不要求翻转连续的几位。要关注的是它们有多少位不相同。

    d[i][j]表示第i步操作后有j位不相同的方法数。

    先把100以内的组合数推出来然后慢慢搞搞就行。

    d[i][j] = d[i-1][s]*C[s][x]*C[n-s][y]

    解释一下:s是从上一步可以推导过来的一些状态,即上一步完成后有s位不相同,

    显然 max{0,j-m} <= s <= min{n,j+m} 。而且s还与j和m的奇偶性有关。j和m奇偶性相同则s为偶,否则为奇。

    每一步操作,我们都可以在上一种状态下先减少x位不同,再增加y位不同,使得此次操作完后不同的数目变成j。每次翻转m位,即x+y=m。

    最后的答案是 d[k][0]。



    #include<cassert>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<set>
    #include<queue>
    #include<map>
    using namespace std;
    #define rep(i,f,t) for(int i = (f), _end = (t); i <= _end; ++i)
    #define clr(c,x) memset(c,x,sizeof(c));
    #define debug(x) cout<<"debug  "<<x<<endl;
    const int INF = 0x3f3f3f3f;
    typedef long long int64;

    inline int RD(){
        int res;
        scanf("%d",&res);
        return res;
    }

    #define Rush for(int casn = RD(), cas = 1; cas <= casn; ++cas)

    //*******************************************************************************
    const int maxn = 110;
    int64 d[maxn][maxn];
    char s1[maxn],s2[maxn];
    int n,m,k;
    int64 C[maxn][maxn];
    const int mod = 1000000009;

    void calC(){
        C[0][0] = 1;
        rep(i,1,100)rep(j,0,i){
            if(j == 0 || i == j){ C[i][j] = 1; continue; }
            if(i - j >= j)
                C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;
            else
                C[i][j] = C[i][i-j];
        }
    }
    int main(){
        //freopen("3791.in","r",stdin);
        //freopen("3791.out","w",stdout);
        calC();
        while(scanf("%d%d%d",&n,&k,&m) == 3){
            scanf("%s%s",s1,s2);
            int cnt = 0;
            rep(i,0,n-1) cnt += s1[i] != s2[i]; //不同的个数
            clr(d,0);
            d[0][cnt] = 1;
            rep(i,1,k){
                d[i][0] = d[i-1][m];
                rep(j,1,n){
                    int oe = (j&1) != (m&1);    //s的奇偶性
                    rep(s,max(j-m,0),min(j+m,n)){ //从d[i-1][s]推导过来
                        if((s&1) != oe)continue;
                        if(d[i-1][s] == 0)continue;
                        int dt = s - j; //相差的数目(减少的数)
                        int x = (m + dt) >> 1;
                        int y = m - x;
                        if(x <= s && y <= n-s){
                            d[i][j] = (d[i][j] + d[i-1][s] * C[s][x] % mod * C[n-s][y] % mod) % mod;
                        }
                    }
                }
            }
            printf("%lld ",d[k][0]);
        };
        return 0;
    }



    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    《Java并发编程的艺术》 第9章 Java中的线程池
    《Java并发编程的艺术》第6/7/8章 Java并发容器与框架/13个原子操作/并发工具类
    java锁总结
    《Java并发编程的艺术》第5章 Java中的锁 ——学习笔记
    《Java并发编程的艺术》第4章 Java并发编程基础 ——学习笔记
    Java并发编程的艺术(一、二章) ——学习笔记
    redis缓存使用SpringDataRedis
    商城06——solr索引库搭建&solr搜索功能实现&图片显示问题解决
    商城05——首页轮播图显示实现&Redis环境搭建&Redis实现缓存
    商城04——门户网站介绍&商城首页搭建&内容系统创建&CMS实现
  • 原文地址:https://www.cnblogs.com/DSChan/p/4861991.html
Copyright © 2011-2022 走看看