Atcoder Grand Contest 001E - BBQ Hard(组合意义转化,思维题)
Yet another 思维题……
注意到此题 \(n\) 数据范围很大,但是 \(a_i,b_i\) 数据范围很小,这能给我们什么启发呢?
观察题目所求的组合数的形式,我们可以联想到组合数的组合意义(qwq 似乎 AGC 很喜欢放组合意义的题?涨见识了/cy):\(\dbinom{x+y}{x}\) 为从 \((0,0)\) 出发,只能向上或向右走,到达 \((x,y)\) 的方案数。
于是此题可以转化为,对于 \(\forall i,j\) 求出 \((0,0)\) 出发,到达 \((a_i+a_j,b_i+b_j)\) 的方案数。
但是这样貌似还是不好求,于是考虑再进行一个转化,将坐标轴进行平移,即可转化为 \((-a_i,-b_i)\) 到 \((a_j,b_j)\) 的方案数。
故本题等价于求计算两两点之间的路径条数总和。这个可以用一个简单的 \(dp\) 求出,\(dp_{i,j}\) 表示到达 \((x,y)\) 的路径条数,那么有个显然的转移方程 \(dp_{i,j}=dp_{i-1,j}+dp_{i,j-1}+[is_{i,j}]\),其中 \(is_{i,j}\) 表示 \((i,j)\) 是否为起点。这个 \(dp\) 显然可以在 \(\mathcal O(\max^2\{a_i\})\) 的时间内计算求得。最终答案即为 \(\sum\limits_{i=1}^ndp_{a_i,b_i}\)。
还有个小问题,就是通过以上算法求得的答案为对于任意 \(i,j\),\(\dbinom{a_i+a_j+b_i+b_j}{a_i+a_j}\) 的和,而题目要求 \(i<j\),故需将求得的答案减去 \(i=j\) 部分的答案后再除以 \(2\)。至于怎样求 \(i=j\) 部分的答案……这个就不用说了吧,刚学 OI 的时候就会了(bushi)。
时间复杂度 \(\mathcal O(n+m^2)\),其中 \(m=\max a_i\)。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=2e5;
const int DELTA=2002;
const int MOD=1e9+7;
const int INV2=5e8+4;
int n,a[MAXN+5],b[MAXN+5],dp[DELTA*2+5][DELTA*2+5];
int fac[DELTA*4+5],ifac[DELTA*4+5];
void prework(int k){
fac[0]=ifac[0]=ifac[1]=1;
for(int i=2;i<=k;i++) ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=k;i++) fac[i]=1ll*fac[i-1]*i%MOD,ifac[i]=1ll*ifac[i]*ifac[i-1]%MOD;
}
int binom(int x,int y){return 1ll*fac[x]*ifac[x-y]%MOD*ifac[y]%MOD;}
int main(){
scanf("%d",&n);prework(DELTA<<2);int ans=0;
for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]),dp[DELTA-a[i]][DELTA-b[i]]++;
for(int i=1;i<=DELTA*2;i++) for(int j=1;j<=DELTA*2;j++) dp[i][j]=(dp[i][j]+(dp[i-1][j]+dp[i][j-1])%MOD)%MOD;
for(int i=1;i<=n;i++) ans=(ans+dp[DELTA+a[i]][DELTA+b[i]])%MOD;
for(int i=1;i<=n;i++) ans=(ans-binom(a[i]+a[i]+b[i]+b[i],a[i]+a[i])+MOD)%MOD;
ans=1ll*ans*INV2%MOD;printf("%d\n",ans);
return 0;
}
Atcoder Grand Contest 001E - BBQ Hard(组合意义转化,思维题)的更多相关文章
- Atcoder Grand Contest 005 E - Sugigma: The Showdown(思维题)
洛谷题面传送门 & Atcoder 题面传送门 记先手移动棋子的树为红树,后手移动棋子的树为蓝树. 首先考虑一个性质,就是如果与当前红色棋子所在的点相连的边中存在一条边,满足这条边的两个端点在 ...
- AtCoder Grand Contest 019 B - Reverse and Compare【思维】
AtCoder Grand Contest 019 B - Reverse and Compare 题意:给定字符串,可以选定任意i.j且i<=j(当然i==j时没啥卵用),然后翻转i到j的字符 ...
- Atcoder Grand Contest 037B(DP,组合数学,思维)
#include<bits/stdc++.h>using namespace std;const long long mod = 998244353;string s;int a[3000 ...
- Atcoder Grand Contest 037C(贪心,优先队列,思维)
#define HAVE_STRUCT_TIMESPEC//编译器中time.h和phread.h头文件中timespec结构体重名,故加此行#include<bits/stdc++.h> ...
- AtCoder Grand Contest 011
AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\( ...
- AtCoder Grand Contest 031 简要题解
AtCoder Grand Contest 031 Atcoder A - Colorful Subsequence description 求\(s\)中本质不同子序列的个数模\(10^9+7\). ...
- AtCoder Grand Contest 007
AtCoder Grand Contest 007 A - Shik and Stone 翻译 见洛谷 题解 傻逼玩意 #include<cstdio> int n,m,tot;char ...
- AtCoder Grand Contest 006
AtCoder Grand Contest 006 吐槽 这套题要改个名字,叫神仙结论题大赛 A - Prefix and Suffix 翻译 给定两个串,求满足前缀是\(S\),后缀是\(T\),并 ...
- AtCoder Grand Contest 005
AtCoder Grand Contest 005 A - STring 翻译 给定一个只包含\(ST\)的字符串,如果出现了连续的\(ST\),就把他删去,然后所有位置前移.问最后剩下的串长. 题解 ...
随机推荐
- 全场景效能平台猪齿鱼常用的前端css实现方案
居中 最常用的height + line-height,以及margin:0 auto的居中方式就不再阐述,以下介绍两种容错性高的实现方案. flex布局实现 猪齿鱼前端日常开发中,我们多以f ...
- [Git系列] Git 基本概念
版本控制系统 版本控制系统是一种帮助软件开发者实现团队合作和历史版本维护的软件,一个版本控制系统应具备以下列出的这几个基本功能: 允许开发者并发工作: 不允许一个开发者覆写另一个开发者的修改: 保存所 ...
- elasticsearch使用ik中文分词器
elasticsearch使用ik中文分词器 一.背景 二.安装 ik 分词器 1.从 github 上找到和本次 es 版本匹配上的 分词器 2.使用 es 自带的插件管理 elasticsearc ...
- (五)、Docker 容器数据卷
1.什么是数据卷 将运用与运行的环境打包形成容器运行 ,运行可以伴随着容器,但是我们对数据的要求希望是持久化的 容器之间希望有可能共享数据 Docker容器产生的数据,如果不通过docker comm ...
- Qt坐标转换系统的理解
转 https://blog.csdn.net/hgcprg/article/details/53537106 今天又看了一篇对Qt坐标转换系统以及QTransform的博客,作者讲的非常透彻,链接如 ...
- 个人宽带如何开启IPv6网络访问
IPv6是大势所趋,就在前段时间湖南联通发布公告,对家庭宽带提供 IPv6 地址,不再提供 IPv4地址,那本文就介绍 个人宽带如何开启 IPv6网络访问. 湖南联通停止向普通家庭宽带用户提供公网 I ...
- CDP客户数据管理平台体系化搭建
一.Cdp系统简介 1.基本概念 客户数据平台(Customer-Data-Platform),简称CDP:通过采集多方客户数据(主体与线索)等,从而进行精准的客户分析和人群细分,进而实现高效的客户维 ...
- Linux下的 sniff-andthen-spoof程序编写
Linux下的 sniff-andthen-spoof程序编写 一.任务描述 在本任务中,您将结合嗅探和欺骗技术来实现以下嗅探然后欺骗程序.你需要两台机器在同一个局域网.从机器A ping IP_X, ...
- 关于Arrays类的静态方法asList()
Array.asList():是数组转成集合的方法 List<String> list = Arrays.asList(new String[]{"AA", " ...
- 【Go语言学习笔记】函数做参数和闭包
函数做参数 在Go语言中,函数也是一种数据类型,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型.类似于重写(同名覆盖). 回调函数:函数有一个参数是函数类型,这个 ...