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. 最高 ...
随机推荐
- Unity3D之Mesh(二)为三角形添加纹理
一.直接開始上步驟 首先繪製一個三角形 創建一個材質,以便後續使用: 1)材質使用的貼圖 2)上代碼 using UnityEngine; using System.Collections; /* = ...
- 12 Python 函数
初识函数定义与调用 定义:def 关键词开头,空格之后接函数名称和圆括号(),最后还有一个":". def 是固定的,不能变,必须是连续的def三个字母,不能分开...它们要相亲相 ...
- JavaUtil_09_通用工具类-01_Hutool
一.重要的官方资料 1. Hutool 官网 2. Hutool 参考文档 3. Hutool API文档
- 图的Tarjan算法
“Tarjan有三种算法 你们知道吗”——Tar乙己 void tarjan(int x) { low[x]=dfn[x]=++ind; q[++top]=x;mark[x]=; for(int i= ...
- poj 1273 Drainage Ditches(最大流,E-K算法)
一.Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clove ...
- 人物-IT-柳传志:柳传志
ylbtech-人物-IT-柳传志:柳传志 柳传志,英文名:Chuanzhi Liu,男,汉族,中共党员,1944年4月出生于江苏镇江,联想控股股份有限公司董事长,联想集团创始人. 企业家.投资家.全 ...
- Python知识点: __import__
用法:libvirt = __import__('libvirt') help(__import__) __import__(...) __import__(name, globals={}, ...
- 【P2P网贷新手入门】详解借款标的种类及其风险
不同于国外的网贷平台以信用借款标为主,在中国,我们投资网贷平台会看到多样借款标,而投资人往往弄不清自己投资的标属于什么类型的标,特点怎么样,风险如何. 抵 押 标 定义:借款人用自己的房屋车辆等实物在 ...
- java基础知识(7)---多态
多 态:(面向对象特征之一):函数本身就具备多态性,某一种事物有不同的具体的体现.体现:父类引用或者接口的引用指向了自己的子类对象.//Animal a = new Cat();多态的好处:提高了程序 ...
- C#读写.ini文件
转载来源: http://blog.csdn.net/source0573/article/details/49668079 https://www.cnblogs.com/wang726zq/arc ...