AtCoder1983 [AGC001E] BBQ Hard
Posted yspm
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder1983 [AGC001E] BBQ Hard相关的知识,希望对你有一定的参考价值。
一道比较好的组合题
Description
给定 (n) 个点对,求:
[sum^n_{i=1}sum^n_{j=i+1}inom {x_i+x_j+y_i+y_j}{x_i+x_j}
]
(nle 2 imes10^5 x_i,y_i le 2000)
Solution
暴力是不可能的对吧
我们发现一个 (inom{x+y}{x}) 的几何含义是从 ((0,0)) 到 ((x,y)) 的路径条数
转化题意:
给定 (n) 个点 ((x_i,y_i)),每个点可以拆成 ((x_i,y_i)) 和 ((-x_i,-y_i))
求在第三象限内找一个点,再在第一象限内找一个点的不同的路径数
我们首先可以对这个坐标进行 (dp) ,求从底下向上的路径(其实就是杨辉的那个求法)
(这里需要注意一下坐标为负的问题,如果开大数据范围可能是要离散吗?博主并不是很清楚)
最后统计答案,要减去相同点的情况,即 (inom {x_i+x_+y_i+y_i}{x_i+x_i}),然后除以 (2)
这里需要组合数
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k==‘-‘) f=-1;
while(isdigit(k)) res=res*10+k-‘0‘,k=getchar();
return res*f;
}
const int mod=1e9+7,N=4e3+100,M=2e5+10,s=2010;
int inv[M],fac[M];
int n,x[M],y[M],f[N][N];
inline void prework()
{
inv[0]=inv[1]=1; fac[0]=1;
for(int i=1;i<M;++i) fac[i]=fac[i-1]*i%mod;
for(int i=2;i<M;++i) inv[i]=mod-mod/i*inv[mod%i]%mod;
for(int i=1;i<M;++i) inv[i]*=inv[i-1],inv[i]%=mod;;
return ;
}
inline int C(int n,int m){return fac[n]*inv[n-m]%mod*inv[m]%mod; }
signed main()
{
prework(); n=read();
for(int i=1;i<=n;++i) x[i]=read(),y[i]=read(),f[s-x[i]][s-y[i]]++;
for(int i=1;i<=(s<<1);++i)
{
for(int j=1;j<=(s<<1);++j)
{
f[i][j]+=(f[i][j-1]+f[i-1][j])%mod; f[i][j]%=mod;
}
}
int ans=0;
for(int i=1;i<=n;++i)
{
ans+=f[s+x[i]][s+y[i]]; ans%=mod;
ans-=C((x[i]<<1)+(y[i]<<1),(x[i]<<1));
ans+=mod; ans%=mod;
}printf("%lld
",ans*inv[2]%mod);
return 0;
}
}
signed main(){return yspm::main();}
Review
把不可求的组合数转化到几何上面,换成路径统计的那种做法来因值域降低复杂度
最后:逆元累乘的时候记得取模
以上是关于AtCoder1983 [AGC001E] BBQ Hard的主要内容,如果未能解决你的问题,请参考以下文章