博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ZOJ 3791 An Easy Game [组合计数]
阅读量:5295 次
发布时间:2019-06-14

本文共 2656 字,大约阅读时间需要 8 分钟。

题目地址:

    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 
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 else53 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 }

转载于:https://www.cnblogs.com/Lattexiaoyu/p/3855190.html

你可能感兴趣的文章
关于 Go2Shell (Go2Shell 可以在 Finder 中打开当前目录的终端窗口,是一个对开发者来说非常有用的App)...
查看>>
2008年我买了一本书 书名叫“PHP 6”
查看>>
管道,数据共享,进程池
查看>>
UITableView beginUpdate和endUpdate使用的前提
查看>>
Java基础--面向对象编程4(多态)
查看>>
CSS
查看>>
shell 管道和tee使用时获取前面命令返回值
查看>>
[LeetCode] 55. Jump Game_ Medium tag: Dynamic Programming
查看>>
[Cypress] Stub a Post Request for Successful Form Submission with Cypress
查看>>
[TypeScript] Understanding Generics with RxJS
查看>>
一、基础篇--1.3进程和线程-基本概念
查看>>
Linux kernel ‘ioapic_read_indirect’函数拒绝服务漏洞
查看>>
WordPress GRAND FlAGallery插件“s”跨站脚本漏洞
查看>>
如何组织一个高效的开发团队
查看>>
.NET多语言切换,配置
查看>>
Python学习之路_day_03(逻辑运算与数据类型)
查看>>
ACM模板——次短路及K短路
查看>>
Internet History, Technology and Security (Week5.2)
查看>>
20个很有用的PHP类库
查看>>
java 中间 final修饰符
查看>>