AGC001E BBQ Hard 组合、递推
题意:给出长度为$N$的两个正整数序列$A_i,B_i$,求$\sum\limits_{i=1}^N \sum\limits_{j=i+1}^N C_{A_i+A_j+B_i+B_j}^{A_i+B_i}$。$N \leq 2 \times 10^5$
给出两种数据范围以及对应做法:
①$1 \leq A_i,B_i \leq 2000$(原题数据范围)
我们可以发现$C_{A_i+A_j+B_i+B_j}^{A_i+B_i}$就相当于在平面直角坐标系上限定每一次只能向上或者向右走一个单位的情况下,从$(-A_i,-B_i)$走到$(A_j,B_j)$的方案数量,所以原来的题目就可以抽象为一些第三象限的点限定每一次只能向上或者向右走一个单位的情况下走到第一象限中的任意一个点的方案数的和。我们可以将所有$(-A_i,-B_i)$的权值设为$1$,然后递推得到每一个$(A_j,B_j)$的方案数即可。注意:要将$(-A_i,B_i)$到$(A_i,B_i)$的路径方案数减掉(直接组合数即可),同时因为一个数对会被算两边,所以最后要乘上$2$的逆元。总时间复杂度为$O(N+\text{值域}^2)$
- #include<bits/stdc++.h>
- using namespace std;
- inline int read(){
- ;
- ;
- char c = getchar();
- while(c != EOF && !isdigit(c)){
- if(c == '-')
- f = ;
- c = getchar();
- }
- while(c != EOF && isdigit(c)){
- a = (a << ) + (a << ) + (c ^ ');
- c = getchar();
- }
- return f ? -a : a;
- }
- , MAXN = , MAXM = ;
- ][MAXN + ] , jc[MAXN + << ] = { , } , ny[MAXN + << ] = {} , a[MAXM + ] , b[MAXM + ];
- inline long long poww(long long a , int b){
- ;
- while(b){
- )
- times = times * a % MOD;
- a = a * a % MOD;
- b >>= ;
- }
- return times;
- }
- int main(){
- ; i <= MAXN << ; i++)
- jc[i] = jc[i - ] * i % MOD;
- ny[MAXN << ] = poww(jc[MAXN << ] , MOD - );
- ) - ; i ; i--)
- ny[i] = ny[i + ] * (i + ) % MOD;
- ;
- ; i <= N ; i++){
- a[i] = read();
- b[i] = read();
- f[-a[i] + ][-b[i] + ]++;
- ans = (ans + MOD - jc[a[i] + b[i] << ] * (] % MOD * ny[b[i] << ] % MOD) % MOD;
- }
- ; i <= MAXN ; i++){
- f[i][] += f[i - ][];
- f[][i] += f[][i - ];
- }
- ; i <= MAXN ; i++)
- ; j <= MAXN ; j++)
- f[i][j] = ((f[i][j] + f[i - ][j]) % MOD + f[i][j - ]) % MOD;
- ; i <= N ; i++)
- ans = (ans + f[a[i] + ][b[i] + ]) % MOD;
- cout << ans * poww( , MOD - ) % MOD;
- ;
- }
②$1 \leq A_i,B_i \leq 10^6 , \sum(A_i + B_i) \leq 2 \times 10^7$
注意到后面给的和的条件,思考如何去利用它。
将$C_{A_i+A_j+B_i+B_j}^{A_i+B_i}$稍微变形:
$C_{A_i+A_j+B_i+B_j}^{A_i+B_i}$
$= \sum\limits_{k=0}^{A_i+A_j} C_{A_i+B_i}^k \times C_{A_j+B_j}^{A_i+A_j-k}$
$= \sum\limits_{k=-A_i}^{A_j} C_{A_i+B_i}^{A_i+k} \times C_{A_j+B_j}^{A_j-k}$
$= \sum\limits_{k=-A_i}^{B_i} C_{A_i+B_i}^{A_i+k} \times C_{A_j+B_j}^{A_j-k}$
(至于最后一步,因为$k>B_i$时,$C_{A_i+B_i}^{A_i+k}=0$,而$k>A_j$时$C_{A_j+B_j}^{A_j-k}=0$,所以$A_j$与$B_i$是等价的)
所以我们维护$f_i$表示在计算$now$的答案时$\sum\limits_{j=1}^{now-1}C_{A_j+B_j}^{A_j-i}$的值,然后每一次通过$f$数组得到当前答案,并用当前的状态更新$f$数组即可。
复杂度$O(\sum(A_i + B_i) + N)$
- #include<bits/stdc++.h>
- using namespace std;
- inline int read(){
- ;
- ;
- char c = getchar();
- while(c != EOF && !isdigit(c)){
- if(c == '-')
- f = ;
- c = getchar();
- }
- while(c != EOF && isdigit(c)){
- a = (a << ) + (a << ) + (c ^ ');
- c = getchar();
- }
- return f ? -a : a;
- }
- , MAXN = ;
- << ] , jc[MAXN + ] = { , } , ny[MAXN + ] = {};
- inline long long poww(long long a , int b){
- ;
- while(b){
- )
- times = times * a % MOD;
- a = a * a % MOD;
- b >>= ;
- }
- return times;
- }
- int main(){
- ; i <= MAXN ; i++)
- jc[i] = jc[i - ] * i % MOD;
- ny[MAXN] = poww(jc[MAXN] , MOD - );
- ; i ; i--)
- ny[i] = ny[i + ] * (i + ) % MOD;
- ;
- ; i <= N ; i++){
- long long a = read() , b = read();
- for(int j = -a ; j <= b ; j++)
- ans = (ans + f[MAXN + j] * (long long)jc[a + b] % MOD * ny[a + j] % MOD * ny[b - j]) % MOD;
- for(int j = -b ; j <= a ; j++)
- f[MAXN + j] = (f[MAXN + j] + (long long)jc[a + b] * ny[a - j] % MOD * ny[b + j]) % MOD;
- }
- cout << ans % MOD;
- ;
- }
AGC001E BBQ Hard 组合、递推的更多相关文章
- 2825 codevs危险的组合(递推)
2825 危险的组合 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 钻石 Diamond 题目描述 Description 有一些装有铀(用U表示)和铅(用L表示)的盒子,数量均足够 ...
- Crash的游戏 [组合+递推]
题面 思路 问题转化 这个问题的核心在于,我们需要把"加入一个球.拿出一个球"这两个操作转化一下 因为显然两个操作同时进行的话,我们没有办法从单纯的组合意义去分析 我们首先把$m$ ...
- Codeforces Round #526 C - The Fair Nut and String /// 组合递推
题目大意: 给定原字符序列 找出其中所有子序列满足 1.序列内字符都为a 2.若有两个以上的字符 则相邻两个字符在原序列中两者之间存在字符b 的数量 将整个字符序列用b分开 此时再得到每个b之间a的数 ...
- UVA 557 Burger 排列组合递推
When Mr. and Mrs. Clinton's twin sons Ben and Bill had their tenth birthday, the party was held at t ...
- 逆元 组合A(n,m) C(n,m)递推 隔板法
求逆元 https://blog.csdn.net/baidu_35643793/article/details/75268911 int inv[N]; void init(){ inv[] = ; ...
- P1759 通天之潜水(不详细,勿看)(动态规划递推,组合背包,洛谷)
题目链接:点击进入 题目分析: 简单的组合背包模板题,但是递推的同时要刷新这种情况使用了哪些物品 ac代码: #include<bits/stdc++.h> using namespace ...
- 递推,求至少连续放置三个U的危险组合
UVA580-Critical Mass 题意 有两种方块,L和U,有至少三个连续的U称为危险组合,问有多少个危险组合 solution: 至少这个概念比较难求 ,所以转化为(1ll<<n ...
- 【bzoj 2339】[HNOI2011]卡农(数论--排列组合+逆元+递推)
题意:从编号为 1~N 的音阶中可选任意个数组成一个音乐片段,再集合组成音乐篇章.要求一个音乐篇章中的片段不可重复,都不为空,且出现的音符的次数都是偶数个.问组成 M 个片段的音乐篇章有多少种.答案取 ...
- 【66测试20161115】【树】【DP_LIS】【SPFA】【同余最短路】【递推】【矩阵快速幂】
还有3天,今天考试又崩了.状态还没有调整过来... 第一题:小L的二叉树 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣.所以,小L当时卡在了二叉树. ...
随机推荐
- Python之历史
一.python简单介绍 python的创始人:吉多·范罗苏姆(Guido van Rossum),于1989年开始编写,到1991年完成了第一个python编译器.它是用C语言实现的,并能够调用C语 ...
- 搜狐eHR团队-曾经一起奋斗过的~
昨天所有搜狐eHR团队同事再相聚(在职+离职),大家聊的都很开心,共同回顾了eHR项目从无到有的过程. 非常感谢在搜狐的工作经历,自己成长很多,目前大家分布在各个公司为eHR做着贡献,大家都注意身体~ ...
- Python 基于python实现单例模式
基于python实现单例模式 by:授客 QQ:1033553122 概念 简单说,单例模式(也叫单件模式)的作用就是保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个(当然也 ...
- JQuery请求数据的方式
/*$.ajax常用的几个参数 // 1.url:要求为String类型的参数,(默认为当前页地址)发送请求的地址. // 2.type:要求为String类型的参数,请求方式(post或get)默认 ...
- CentOS7:解决Packagekit占用yum问题
首先: vim /etc/yum/pluginconf.d/langpacks.conf 将第一行:enable=1改为enable=0 然后执行一下yum命令,发现还会占用,杀死线程即可.
- Python创建空DataFrame及添加行数据
# 创建空DataFrame df = pd.DataFrame(columns = ['YJML','EJML','SJML','WZLB','GGXHPZ','CGMS']) # 插入数据(忽略索 ...
- [20170909]为什么是12秒.txt
[20170909]为什么是12秒.txt --//在开发程序时我一般会强调开发尽量不要写一些自定义函数,往往可能导致CPU忙.--//例子很像这样: CREATE OR REPLACE FUNCTI ...
- asp.net webapi 自定义身份验证
/// <summary> /// 验证 /// </summary> /// Account API账号 /// TimeStamp 请求时间 /// Sign 所有请求参数 ...
- sleep和Sleep区别
windows Sleep 单位是毫秒 linux sleep 单位是秒
- 国内常用的几个NTP时间服务器
问题描述: 经常Windows或者Linux系统上面的时间跟我们本地的时间不一致 有时候就是Windows的Internet时间设置里面的Windows自带的时间同步服务器不好使 Linux配置NTP ...