cf785D(组合数学)
题目链接: http://codeforces.com/problemset/problem/785/D
题意: 左边全为 '(' 右边全为 ')' 且两者数量想等的字符串称为 RSBS. 给出一个由 '(' 和 ')' 组成的字符串, 问其有多少子序列是 RSBS.
思路: 可以先预处理一下, 用 a[i] 记录 i 前面(包括 i 这个位置)的 '(' 的数目, b[i] 记录 i 后面(包括 i 这个位置)的 ')' 的数目, 然后从左往右枚举以 '(' 结尾的情况,
那么当前情况下的 RSBS 数目为:
C(a[i] - 1, 0) * C(b[i], 1) + C(a[i] - 1, 1) * C(b[i], 2) + C(a[i] - 1, 2) * C(b[i], 3) + ...
= ∑min(a-1, b-1)0 C(a - 1, x) * C(b, x + 1)
= ∑min(a-1, b-1)0 C(a - 1, a - 1 - x) * C(b, x + 1)
= C(a - 1 + b, a) (范德蒙恒等式)
然后将所有情况的 RSBS 数目累加一下就好啦.
注意这里的组合数比较大, 取模的话需要用到 exgcd 或者 快速幂.
代码1: 快速幂求组合数取模 C(n, m) % mode = (n! % mode) * get_pow((n - m)! * m! % mode, mode - 2) % mode. (这个公式能通过费马小定理变换得到).
#include <iostream>
#define ll long long
using namespace std; const int mode = 1e9 + ;
const int MAXN = 2e5 + ;
ll a[MAXN], b[MAXN], gel[MAXN];
string s; ll get_pow(ll x, int n){
ll ans = ;
while(n){
if(n & ) ans = ans * x % mode;
x = x * x % mode;
n >>= ;
}
return ans;
} int main(void){
ll ans = ;
cin >> s;
if(s[] == '(') a[] = ;
for(int i = ; i < s.size(); i++){
if(s[i] == '(') a[i] = a[i - ] + ;
else a[i] = a[i - ];
}
for(int i = s.size() - ; i >= ; i--){
if(s[i] == ')') b[i] = b[i + ] + ;
else b[i] = b[i + ];
}
gel[] = ;
for(int i = ; i < MAXN; i++){
gel[i] = gel[i - ] * i % mode;
}
for(int i = ; i < s.size(); i++){
if(s[i] == ')') continue;
ll cnt1 = a[i], cnt2 = a[i] + b[i] - ;
ans = (ans + (gel[cnt2] * get_pow(gel[cnt1] * gel[cnt2 - cnt1] % mode, mode - )) % mode) % mode;
}
cout << ans << endl;
return ;
}
代码2: 用乘法逆元求得组合数取模
#include <iostream>
#define ll long long
using namespace std; const int mode = 1e9 + ;
const int MAXN = 2e5 + ;
ll a[MAXN], b[MAXN], gel[MAXN];
string s; void exgcd(ll a, ll b, ll &x, ll &y){
if(!b){
y = ;
x = ;
return;
}
exgcd(b, a % b, y, x);
y -= a / b * x;
} int main(void){
ll ans = ;
cin >> s;
if(s[] == '(') a[] = ;
for(int i = ; i < s.size(); i++){
if(s[i] == '(') a[i] = a[i - ] + ;
else a[i] = a[i - ];
}
for(int i = s.size() - ; i >= ; i--){
if(s[i] == ')') b[i] = b[i + ] + ;
else b[i] = b[i + ];
}
gel[] = ;
for(int i = ; i < MAXN; i++){
gel[i] = gel[i - ] * i % mode;
}
for(int i = ; i < s.size(); i++){
if(s[i] == ')') continue;
ll cnt1 = a[i], cnt2 = a[i] + b[i] - ;
ll cc1 = gel[cnt2], cc2 = gel[cnt2 - cnt1] * gel[cnt1] % mode;
ll x, y;
exgcd(cc2, mode, x, y);
x = (x % mode + mode) % mode;
ans = (ans + (cc1 * x) % mode) % mode; }
cout << ans << endl;
return ;
}
cf785D(组合数学)的更多相关文章
- poj 3734 Blocks 快速幂+费马小定理+组合数学
题目链接 题意:有一排砖,可以染红蓝绿黄四种不同的颜色,要求红和绿两种颜色砖的个数都是偶数,问一共有多少种方案,结果对10007取余. 题解:刚看这道题第一感觉是组合数学,正向推了一会还没等推出来队友 ...
- 组合数学or not ---- n选k有重
模板问题: 1. 取物品 (comb.pas/c/cpp) [问题描述] 现在有n个物品(有可能相同),请您编程计算从中取k个有多少种不同的取法.[输入] 输入文件有两行,第一行包含两个整数n,k(2 ...
- 组合数学(全排列)+DFS CSU 1563 Lexicography
题目传送门 /* 题意:求第K个全排列 组合数学:首先,使用next_permutation 函数会超时,思路应该转变, 摘抄网上的解法如下: 假设第一位是a,不论a是什么数,axxxxxxxx一共有 ...
- uestc1888 Birthday Party 组合数学,乘法原理
题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=25539#problem/G 题目意思: 有n个人,每个人有一个礼物,每个人能拿 ...
- UVA 11076 Add Again 计算对答案的贡献+组合数学
A pair of numbers has a unique LCM but a single number can be the LCM of more than one possiblepairs ...
- POJ3252——Round Number(组合数学)
Round Numbers DescriptionThe cows, as you know, have no fingers or thumbs and thus are unable to pla ...
- HDU4675【GCD of scequence】【组合数学、费马小定理、取模】
看题解一开始还有地方不理解,果然是我的组合数学思维比较差 然后理解了之后自己敲了一个果断TLE.... 我以后果然还得多练啊 好巧妙的思路啊 知识1: 对于除法取模还需要用到费马小定理: a ^ (p ...
- hdu 4810 Wall Painting (组合数学+二进制)
题目链接 下午比赛的时候没有想出来,其实就是int型的数分为30个位,然后按照位来排列枚举. 题意:求n个数里面,取i个数异或的所有组合的和,i取1~n 分析: 将n个数拆成30位2进制,由于每个二进 ...
- CCF 201312-4 有趣的数 (数位DP, 状压DP, 组合数学+暴力枚举, 推公式, 矩阵快速幂)
问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次. 2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前. 3. 最高 ...
随机推荐
- windows 批处理ping ip
//pingSingleIp ;;@Echo off @for /f "tokens=1-4 delims=." %%i in (ip.txt) do (@ping -w 600 ...
- linux-常用指令1
掌握下面的命令是最基本的噢!那是我们使用一个系统最基本的操作. 玩过dos么,其实,linux下的文件操作和dos差不多.没什么难的,多练习就记住了.下面如果有条件的话请跟我一样操作吧!百看不如一做. ...
- codeforces 627B B. Factory Repairs(线段树)
B. Factory Repairs time limit per test 4 seconds memory limit per test 256 megabytes input standard ...
- codeforces 622D D. Optimal Number Permutation(找规律)
D. Optimal Number Permutation time limit per test 1 second memory limit per test 256 megabytes input ...
- 基于无锁的C#并发队列实现
最近开始学习无锁编程,和传统的基于Lock的算法相比,无锁编程具有其独特的优点,Angel Lucifer的关于无锁编程一文对此有详细的描述. 无锁编程的目标是在不使用Lock的前提下保证并发过程中共 ...
- [转]JS中apply和call的联系和区别
JS中有时常用到 apply 和 call 两个方法,搜索网上很多,整理如下,简单看看这两个联系和区别, 联系: 网上查到关于apply和call的定义:这两个方法都能劫持另外一个对象的方法,继承另外 ...
- Python命令模块argparse学习笔记(四)
默认参数 ArgumentParser.set_defaults(**kwargs) set_defaults()可以设置一些参数的默认值 >>> parser = argparse ...
- Python函数(十二)-迭代器
字符串,列表,元组,字典,集合,生成器这些能通过for循环来遍历的数据类型都是可迭代对象 可通过isinstance判断是不是可迭代对象 >>> from collections i ...
- 第七篇 elasticsearch 链接mysql不会更新
这是我键的索引 "settings":{ "number_of_shards":3, "number_of_replicas":2 }, & ...
- eclipse 远程操作HIVE
首先启动HiveServer hive --service hiveserver 10000 & 创建工程 引入包: 代码(简单的查询): package com.hive.jdbc; imp ...