ZOJ 3791 An Easy Game [组合计数]

题目地址:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3791

题目描述:

给定两个长度为n的01串s1,s2,要求用k步,每一步反转s1的m个位置的数码(即0变为1,1变为0),问能有多少种做法,在k步之后将s1变成s2。

1 <= n <= 100, 0 <= k <= 100, 0 <= m <= n.

解题思路:

典型的组合计数问题。

  1. 首先比较s1和s2,记s1和s2数码不同的位置有n1个,数码相同的位置有n2个。
  2. 计数,如果第k1步结束后,s1和s2有odd个不同的位置,even个相同的位置(odd + even = n)的情况有a[k1][odd]种方法。从odd中取出i个,从even中取出j个进行反转(I + j = m),取法有C[odd][i] * C[even][j]种。不难看出计数方程:

a[k1 + 1][odd – I + j] += a[k1][odd] * C[odd][i] * C[even][j];

  1. 最后结果就是 a[k][0] (因为没有位置数码不同)

源代码:

 1 //zoj3791_zzy_2014.07.19_AC_combinatorial counting
 2 #include <iostream>
 3
 4 using namespace std;
 5
 6 typedef long long LL;
 7
 8 class EasyGame
 9 {
10 public:
11     EasyGame(LL N, LL K, LL M): n(N), k(K), m(M) {
12         ans = 0;
13         ini();
14         for(int i = 0; i < 2; ++i)
15             for(int j = 0; j <= n; ++j)
16                 a[i][j] = 0;
17     }
18     void getString();
19     void solve();
20     int getAns();
21 private:
22     static const LL mod = 1000000009;
23     LL n, k, m, n1, n2, ans;
24     string s1, s2;
25     LL C[101][101];
26     LL a[2][101];
27     void ini();
28 };
29
30 void EasyGame::ini()
31 {
32     C[0][0] = 1;
33     C[1][0] = 1;
34     C[1][1] = 1;
35     for(int i = 2; i <= n; ++i) {
36         C[i][0] = 1;
37         C[i][i] = 1;
38         for(int j = 1; j < i; ++j) {
39             C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;
40         }
41     }
42 }
43
44 void EasyGame::getString()
45 {
46     cin >> s1;
47     cin >> s2;
48     n1 = n2 = 0;
49     for(int idx = 0; idx < s1.size(); ++idx) {
50         if(s1[idx] != s2[idx])
51             n1++;
52         else
53             n2++;
54     }
55 }
56
57 void EasyGame::solve()
58 {
59     a[0][n1] = 1;
60     for(int step = 1; step <= k; ++step) {
61         for(int idx = 0; idx <= n; ++idx)
62             a[step % 2][idx] = 0;
63         for(int odd = 0; odd <= n; ++odd) {
64             int even = n - odd;
65             for(int i = 0; i <= m; ++i) {
66                 int j = m - i;
67                 if(i > odd) break;
68                 if(j > even) continue;
69                 int odd2 = odd - i + j;
70                 a[step % 2][odd2] += a[(step - 1) % 2][odd] * (C[odd][i] * C[even][j] % mod) % mod;
71                 a[step % 2][odd2] %= mod;
72             }
73         }
74     }
75     ans = a[k % 2][0];
76 }
77
78 int EasyGame::getAns()
79 {
80     return ans;
81 }
82
83 int main()
84 {
85     LL N, K, M;
86     while(cin >> N >> K >>M)
87     {
88         EasyGame *egp = new EasyGame(N, K, M);
89         egp -> getString();
90         egp -> solve();
91         cout << egp -> getAns() << endl;
92     }
93     return 0;
94 }

ZOJ 3791 An Easy Game [组合计数]

时间: 2024-10-27 12:34:56

ZOJ 3791 An Easy Game [组合计数]的相关文章

zoj 3791 An Easy Game dp

An Easy Game Time Limit: 2 Seconds      Memory Limit: 65536 KB 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 ch

ZOJ 3791 An easy game DP+组合数

给定两个01序列,每次操作可以任意改变其中的m个数字 0变 1  1 变 0,正好要变化k次,问有多少种变法 dp模型为dp[i][j],表示进行到第i次变化,A,B序列有j个不同的 变法总和. 循环k次,每次针对m,向那j个不同 分1-j个即可,不过要用到组合数,因为对每个数操作不同都不一样 最后结果就是 dp[k][0] #include <iostream> #include <cstdio> #include <cstring> #include <alg

zoj How Many Sets I(组合计数)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4535 一个集合s有n个元素,求满足这样的集合序列{s1,s2....sk}使S1 ∩ S2 ∩ ... ∩ Sk = ?,si是s的子集. 从每个元素考虑会使问题变得简单.首先n个元素是相互独立的,单独考虑第i个元素,它在k个子集的所有情况是2^k,其中有一种情况是k个子集都有第i个元素,这一种情况正好不是我们想要的,所以合法的应该是2^k-1,那么n个元素就是( 2^k-1

Yue Fei&#39;s Battle(组合计数递推)

//求一个直径为 k 的树有多少种形态,每个点的度不超过 3 // 非常完美的分析,学到了,就是要细细推,并且写的时候要细心 还有除法取模需要用逆元 #include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> using namespace std; #define MOD 1000000007 #define L

POJ 1496 POJ 1850 组合计数

Code Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8256 Accepted: 3906 Description Transmitting and memorizing information is a task that requires different coding systems for the best use of the available space. A well known system is t

bzoj 1004 Cards 组合计数

这道题考察的是组合计数(用Burnside,当然也可以认为是Polya的变形,毕竟Polya是Burnside推导出来的). 这一类问题的本质是计算置换群(A,P)中不动点个数!(所谓不动点,是一个二元组(a,p),a∈A,p∈P ,使得p(a)=a,即a在置换p的作用后还是a). Polya定理其实就是告诉了我们一类问题的不动点数的计算方法. 对于Burnside定理的考察,我见过的有以下几种形式(但归根结底还是计算不动点数): 1.限制a(a∈A)的特点,本题即是如此(限制了各颜色个数,可以

POJ 3252 组合计数

Round Numbers Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9149 Accepted: 3248 Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors', 'Ro,

HDU4675-GCD of Sequence(数论+组合计数)

GCD of Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 949    Accepted Submission(s): 284 Problem Description Alice is playing a game with Bob. Alice shows N integers a1, a2, -, aN, an

[HDU 3461] Saving Beans &amp; 组合计数Lucas定理模板

Saving Beans Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description Although winter is far away, squirrels have to work day and night to save beans. They need plenty of food to get through those long cold