[AGC001E]BBQ Hard
Posted StaroForgin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[AGC001E]BBQ Hard相关的知识,希望对你有一定的参考价值。
BBQ Hard
题解
首先,我们可以考虑组合数是可以被表示成路径的形式的,
(
n
+
m
m
)
\\binomn+mm
(mn+m)可以表示从点
(
0
,
0
)
(0,0)
(0,0)到点
(
n
,
m
)
(n,m)
(n,m)的简单路径(向上走或向右走)数。
那么显然,我们
(
a
i
+
a
j
+
b
i
+
b
j
a
i
+
a
j
)
\\binoma_i+a_j+b_i+b_ja_i+a_j
(ai+ajai+aj+bi+bj)可以表示从点
(
0
,
0
)
(0,0)
(0,0)到点
(
a
i
+
a
j
,
b
i
+
b
j
)
(a_i+a_j,b_i+b_j)
(ai+aj,bi+bj)的简单路径数量。但显然
我们不可能对于每个
(
a
i
+
a
j
,
b
i
+
b
j
)
(a_i+a_j,b_i+b_j)
(ai+aj,bi+bj)都求一条路径,但不妨再观察一下,
(
0
,
0
)
(0,0)
(0,0)到
(
a
i
+
a
j
,
b
i
+
b
j
)
(a_i+a_j,b_i+b_j)
(ai+aj,bi+bj)的路径条数显然是等价于
(
−
a
i
,
−
b
i
)
(-a_i,-b_i)
(−ai,−bi)到
(
a
j
,
b
j
)
(a_j,b_j)
(aj,bj)的路径数的。
我们可以用
d
p
dp
dp求出所有的
(
−
a
i
,
−
b
i
)
(-a_i,-b_i)
(−ai,−bi)到所有的
(
a
j
,
b
j
)
(a_j,b_j)
(aj,bj)的路径数。
记
d
p
x
,
y
dp_x,y
dpx,y为所有的
(
−
a
i
,
−
b
i
)
(-a_i,-b_i)
(−ai,−bi)到点
(
x
,
y
)
(x,y)
(x,y)的简单路径数,
∑
j
=
1
n
d
p
a
i
,
b
i
\\sum_j=1^ndp_a_i,b_i
∑j=1ndpai,bi就是答案。
时间复杂度 O ( n + A B ) O\\left(n+AB\\right) O(n+AB)。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 200005
#define MAXM 4005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
typedef long double ld;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f;
const int mo=1e9+7;
const int mod=1e5+3;
const int inv2=5e8+4;
const int jzm=2333;
const int zero=2000;
const int n1=1000;
const int M=100000;
const int orG=3,ivG=332748118;
const long double Pi=acos(-1.0);
const double eps=1e-12;
template<typename _T>
_T Fabs(_T x)return x<0?-x:x;
template<typename _T>
void read(_T &x)
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0')if(s=='-')f=-1;s=getchar();
while('0'<=s&&s<='9')x=(x<<3)+(x<<1)+(s^48);s=getchar();
x*=f;
template<typename _T>
void print(_T x)if(x<0)x=(~x)+1;putchar('-');if(x>9)print(x/10);putchar(x%10+'0');
int gcd(int a,int b)return !b?a:gcd(b,a%b);
int add(int x,int y,int p)return x+y<p?x+y:x+y-p;
void Add(int &x,int y,int p)x=add(x,y,p);
int qkpow(int a,int s,int p)int t=1;while(s)if(s&1)t=1ll*t*a%p;a=1ll*a*a%p;s>>=1;return t;
int n,a[MAXN],b[MAXN],dp[MAXM][MAXM],ans,fac[MAXM*2],inv[MAXM*2],ff[MAXM*2];
void init()
fac[0]=fac[1]=inv[0]=inv[1]=ff[1]=1;
for(int i=2;i<=8000;i++)
fac[i]=1ll*i*fac[i-1]%mo,
ff[i]=1ll*(mo-mo/i)*ff[mo%i]%mo,
inv[i]=1ll*ff[i]*inv[i-1]%mo;
int C(int x,int y)
if(x<y||x<0||y<0)return 0;
return 1ll*fac[x]*inv[y]%mo*inv[x-y]%mo;
signed main()
read(n);init();
for(int i=1;i<=n;i++)read(a[i]),read(b[i]),dp[zero-a[i]][zero-b[i]]++;
for(int i=1;i<=8000;i++)
for(int x=max(0,i-4000),y=min(4000,i);x<=4000&&y>=0;x++,y--)
if(x)Add(dp[x][y],dp[x-1][y],mo)AtCoder1983 [AGC001E] BBQ Hard