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\),就把他删去,然后所有位置前移.问最后剩下的串长. 题解 ...
随机推荐
- Golang通脉之方法
方法和接收者 Go语言中的方法(Method)是一种作用于特定类型变量的函数.这种特定类型变量叫做接收者(Receiver).接收者的概念就类似于其他语言中的this或者 self. Go 语言中同时 ...
- [技术博客]Django框架-后端的搭建
目录 Django框架-后端的搭建 前言 环境的部署 项目的创建 app的使用 创建app 修改配置文件 app中数据表的构建 前端接口 接口的路径 运行服务器 验证后端 Django框架-后端的搭建 ...
- pyinstaller和wordcloud和jieba的使用案列
一.pyinstaller库 1.简介 pyinstaller库:将脚本程序转变为可执行(.exe)格式的第三方库 注意:需要在.py文件所在目录进行以下命令,图标扩展名是.ico 2.格式: pyi ...
- 2021.9.25考试总结[NOIP模拟61]
终于有点阳间题了然而挂了60pts 哈哈 T1 交通 类似简单题,限制看似很复杂,但不难发现当确定一条边是否被删后会产生裙带关系,很多边会跟着自动被确定是否被删. 仔细观察可以得出这种关系会构成偶环结 ...
- Allegro如何测量距离,测距工具的使用
http://www.allegro-skill.com/thread-2480-1-1.html
- numpy数组的计算
1.数组的形状 查看数组的形状: import numpy as np a = np.array([[1, 2, 3, 4, 5], [5, 6, 7, 8, 9]]) print(a.shape) ...
- 认真讲说static关键字
static 关键字主要有以下四种使用场景 修饰成员变量和成员方法 静态代码块 修饰类(只能修饰内部类) 静态导包(用来导入类中的静态资源,1.5之后的新特性) 修饰成员变量和成员方法(常用) 被 s ...
- 洛谷 P5657 [CSP-S2019] 格雷码
链接: P5657 分析: 签到题,不过也有不少细节. 数据范围需要开 unsigned long long ,前年也有很多人因此丢了5分. pow 会出现神必错误,需要手写一个 mpow 函数. 算 ...
- 【做题记录】max-min+1=len 区间计数
(来源:XJ高质量原创题) 原题地址 弱化版:CF526F Pudding Monsters 弱化版 题意:\(n\times n\) 的棋盘上有 \(n\) 颗棋子,每行每列都有且仅有一颗棋子,求出 ...
- CSP-S 2021 爆零记
前言 本人今年高二蒟蒻OIer,高一刚刚接触OI. 感觉可能要直接退役了555~ 希望还有机会靠NOIP翻盘 Day - 暑假 为了备战CSP提前返校,与xzh一起划水,总之刷了不少题,我也大受震撼 ...