[AGC001E] BBQ Hard
Problem Statement
Snuke is having another barbeque party.
This time, he will make one serving of Skewer Meal.
He has a stock of $N$ Skewer Meal Packs. The $i$-th Skewer Meal Pack contains one skewer, $A_i$ pieces of beef and $B_i$ pieces of green pepper. All skewers in these packs are different and distinguishable, while all pieces of beef and all pieces of green pepper are, respectively, indistinguishable.
To make a Skewer Meal, he chooses two of his Skewer Meal Packs, and takes out all of the contents from the chosen packs, that is, two skewers and some pieces of beef or green pepper. (Remaining Skewer Meal Packs will not be used.) Then, all those pieces of food are threaded onto both skewers, one by one, in any order.
(See the image in the Sample section for better understanding.)
In how many different ways can he make a Skewer Meal? Two ways of making a Skewer Meal is different if and only if the sets of the used skewers are different, or the orders of the pieces of food are different. Since this number can be extremely large, find it modulo $10^9+7$.
Constraints
- $2≦N≦200,000$
- $1≦A_i≦2000, 1≦B_i≦2000$
Input
The input is given from Standard Input in the following format:
$N$ $A_1$ $B_1$ $A_2$ $B_2$ : $A_N$ $B_N$
Output
Print the number of the different ways Snuke can make a serving of Skewer Meal, modulo $10^9+7$.
Sample Input 1
3 1 1 1 1 2 1
Sample Output 1
26
题目的意思是,对于所有的不同的 \(i,j\),要在 \(a_i+a_j+b_i+b_j\) 中选出 \(a_i+a_j\) 个位置给牛肉。换言之,求值:
所以这东西怎么求呢?观察到 \(a_i,b_i\le 1000\),考虑能不能使用这个性质。
接下来是很玄学的一步:把 \(C_{a_i+a_j+b_i+b_j}^{a_i+b_i}\) 看作从点 \((0,0)\) 到达 \((a_i+b_i,a_j+b_j)\) 的路径数
但这样 dp 次数有点多,再转化一层,看作从点 \((-a_i,-b_i)\) 走到 \((a_j,b_j)\)
注意到此时两个点已经分别只和 \(i\) 和 \(j\) 有关了。再预处理时将所有 \(dp_{-a_i,-b_i}\) 的值赋值为 1,然后跑完 dp,将所有的 \(dp_{a_i,b_i}\) 的值加起来,复杂度 \(O(\max(a_i,b_i)^2)\)
注意到 \((-a_i,-b_i)\) 到 \((a_i,b_i)\) 的值都不计入答案,可以减去,然后每种情况被算了两次,所以要再除以2.
#include<cstdio>
const int N=2e5+5,M=2005,P=1e9+7,iv2=P+1>>1;
int n,a[N],b[N],ans,c[M<<2][M<<2],f[M<<1][M<<1];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",a+i,b+i),f[M-a[i]][M-b[i]]++;
for(int i=-2000;i<=2000;i++)
for(int j=-2000;j<=2000;j++)
(f[i+M][j+M]+=(f[M+i-1][j+M]+f[i+M][j+M-1])%P)%=P;
for(int i=c[0][0]=1;i<M*4;i++)
{
c[i][0]=c[i][i]=1;
for(int j=1;j<i;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%P;
}
// printf("%d %d\n",c[4][2],c[6][4]);
// printf("%d\n",f[M+1][M+1]);
for(int i=1;i<=n;i++)
{
(ans+=f[a[i]+M][b[i]+M])%=P;
(ans-=c[a[i]+b[i]<<1][a[i]<<1])%=P;
}
printf("%d",1LL*(ans+P)*iv2%P);
}
原文地址:https://www.cnblogs.com/mekoszc/p/17049192.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 详解将数据从Laravel传送到vue的四种方式
- Laravel实现ApiToken认证请求
- laravel 实现划分admin和home 模块分组
- laravel在中间件内生成参数并且传递到控制器中的2种姿势
- 在laravel框架中实现封装公共方法全局调用
- laravel通过a标签从视图向控制器实现传值
- 在Laravel 的 Blade 模版中实现定义变量
- 解决Laravel5.5下的toArray问题
- Laravel基础_关于view共享数据的示例讲解
- 解决在laravel中leftjoin带条件查询没有返回右表为NULL的问题
- 解决laravel资源加载路径设置的问题
- laravel实现前后台路由分离的方法
- laravel5.1框架model类查询的实现方法
- laravel-admin 管理平台获取当前登陆用户信息的例子
- Yii框架Session与Cookie使用方法示例