AT1983-[AGC001E]BBQ Hard【dp,组合数学】

1|0正题

题目链接:https://www.luogu.com.cn/problem/AT1983


1|1题目大意

给出n个数对(ai,bi)

i=1nj=i+1n(ai+bi+aj+bjai+aj)

1n2×105,1ai,bi2000


1|2解题思路

啊遇到这种题目直接上组合意义

然后发现ai,bi很小。上面那个组合数可以变成横着走ai+aj步,竖着走bi+bj步的方案。

之后理解为从(ai,bi)走到(aj,bj)就可以分离i,j了。

因为很小,直接多起点走一次求和就好了,要减去重复的部分。

时间复杂度O(n+max{ai}×max{bi})


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=2e5+10,M=4500,P=1e9+7; ll n,a[N],b[N],f[M][M],fac[N],inv[N],ans; ll C(ll n,ll m) {return fac[n]*inv[m]%P*inv[n-m]%P;} signed main() { scanf("%lld",&n);inv[1]=1; for(ll i=2;i<N;i++)inv[i]=P-inv[P%i]*(P/i)%P; inv[0]=fac[0]=1; for(ll i=1;i<N;i++) fac[i]=fac[i-1]*i%P,inv[i]=inv[i-1]*inv[i]%P; for(ll i=1;i<=n;i++){ scanf("%lld%lld",&a[i],&b[i]); f[2001-a[i]][2001-b[i]]++; } for(ll i=1;i<=4002;i++) for(ll j=1;j<=4002;j++) (f[i][j]+=f[i-1][j]+f[i][j-1])%=P; for(ll i=1;i<=n;i++){ (ans+=f[2001+a[i]][2001+b[i]]%P)%=P; (ans-=C(2*a[i]+2*b[i],2*a[i]))%=P; } printf("%lld\n",(ans+P)*inv[2]%P); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14828335.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(50)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示