zoukankan      html  css  js  c++  java
  • 【题解】AT1983 BBQ Hard (格路)

    【题解】AT1983 BBQ Hard (格路)

    题目就是要求

    [sum_{i=1}^n sum _{j>i}^n {a_i+b_i+a_j+b_j choose a_i+a_j} ]

    其中(nle 2 imes 10^5,a_i,b_iin [1,2000])

    这个式子有很强的组合一样,一个熟练的选手应该发现这个组合数是(x+ychoose s)的形式,也就是对应上了格路问题。这个问题等价于从若干((-a_i,-b_i))((a_j,b_j))的方案数。格路问题另一个解法是值域的DP,于是我们可以简单DP得到所有((-a_i,-b_i))((a_j,b_j))的方案数的和。

    但是有一个边界是,不能((i->j)),并且一个((i,j))只能算一次。所以我单独算一下(i=j)的所以情况的方案,减去之后在除以二。

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<assert.h>
    #define DEBUG(s,a) cerr<<#s" = "<<(s)<<" 
    "[(a)==1]
    
    using namespace std;  typedef long long ll;   char __buf[1<<18],*__c=__buf,*__ed=__buf;
    inline int qr(){
    	int ret=0,f=0,c=getchar();
    	while(!isdigit(c))f|=c==45,c=getchar();
    	while(isdigit(c)) ret=ret*10+c-48,c=getchar();
    	return f?-ret:ret;
    }
    const int maxn=8000+5;
    const int mod=1e9+7;
    int dp[maxn][maxn],N,n,jc[maxn],inv[maxn],A[200000+1],B[200000+1];
    
    inline int MOD(const int&x){return x>=mod?x-mod:x;}
    inline int MOD(const int&x,const int&y){return 1ll*x*y%mod;}
    
    inline int ksm(const int&ba,const int&p){
    	int ret=1;
    	for(int t=p,b=ba;t;t>>=1,b=MOD(b,b))
    		if(t&1) ret=MOD(ret,b);
    	return ret;
    }
    
    void pre(const int&n){
    	jc[0]=inv[0]=1;
    	for(int t=1;t<=n;++t) jc[t]=MOD(jc[t-1],t);
    	inv[n]=ksm(jc[n],mod-2);
    	for(int t=n-1;t;--t) inv[t]=MOD(inv[t+1],t+1);
    	for(int t=1;t<=n;++t) assert(MOD(inv[t],jc[t])==1);
    }
    
    int c(const int&n,const int&m){
    	if(n<m) return 0;
    	return MOD(jc[n],MOD(inv[m],inv[n-m]));
    }
    
    int main(){
    	n=qr();
    	for(int t=1;t<=n;++t) A[t]=qr(),B[t]=qr(),N=max({N,A[t],B[t]});
    	++N;
    	pre(8000);
    	int ans=0;
    	for(int t=1;t<=n;++t) ans=MOD(ans-c(A[t]+A[t]+B[t]+B[t],A[t]+A[t])+mod),dp[N-A[t]][N-B[t]]=MOD(dp[N-A[t]][N-B[t]]+1);
    	for(int t=-N+1;t<N;++t)
    		for(int i=-N+1;i<N;++i)
    			dp[t+N][i+N]=MOD(dp[t+N][i+N]+MOD(dp[-1+t+N][i+N]+dp[t+N][-1+i+N]));
    	for(int t=1;t<=n;++t) ans=MOD(ans+dp[A[t]+N][B[t]+N]);
    	ans=MOD(ans,(mod+1)/2);
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
    
    
  • 相关阅读:
    二叉排序树的建立_查找_插入_删除
    java学习书籍推荐
    Java之路——敬JAVA初学者(作者:MoMo)
    结构体的定义及应用
    java获取缓存通用类
    金额转换为自定义字符串
    WebApi接入Swagger
    webApi的控制台服务
    自动生成缓存Key值的CacheKeyHelper
    DictionaryHelper2
  • 原文地址:https://www.cnblogs.com/winlere/p/12180979.html
Copyright © 2011-2022 走看看