zoukankan      html  css  js  c++  java
  • 【AGC001E】BBQ Hard

    题目

    题目链接:https://atcoder.jp/contests/agc001/tasks/agc001_e
    有 n 个数对 ((a_i,b_i)),求

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

    答案对 (10^9+7) 取模。
    (nleq 200000;1leq a_i,b_ileq 2000)

    思路

    观察到 (a,b) 的取值范围很小,所以复杂度肯定是有关 (a,b) 的。
    考虑 ({a_i+b_i+a_j+b_j choose a_i+a_j}) 的组合意义,其实就是从 ((0,0)) 走到 ((a_i+a_j,b_i+b_j)) 且只能往上和往右的方案数。
    这样还是不好搞,我们可以把起点和终点的横纵坐标分别减去 (a_i)(b_i),也就是从 ((-a_i,-b_i)) 走到 ((a_j,b_j)) 的方案数。
    这样起点和终点就分别只和 (i,j) 有关了。初始化 (f[x][y]=) 集合 ({i|a_i=x,b_i=y}) 的大小,然后往右上方递推即可。
    因为题目中要求 (i<j),所以最后减去 (i=j) 的方案数后除以二即可。
    时间复杂度 (O(n+AB))。其中 (A=max(a_i),B=max(b_i))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=200010,M=2010,MOD=1e9+7;
    int n,ans,a[N],b[N],f[2*M][2*M],g[2*M][2*M];
    
    int main()
    {
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d%d",&a[i],&b[i]);
    		f[M-a[i]][M-b[i]]++;
    	}
    	g[1][1]=1;
    	for (int i=1;i<=4015;i++)
    		for (int j=1;j<=4015;j++)
    		{
    			f[i][j]=(f[i][j]+f[i-1][j]+f[i][j-1])%MOD;
    			g[i][j]=(g[i][j]+g[i-1][j]+g[i][j-1])%MOD;
    		}
    	for (int i=1;i<=n;i++)
    	{
    		ans=(ans+f[a[i]+M][b[i]+M])%MOD;
    		ans=(ans+MOD-g[a[i]*2+1][b[i]*2+1])%MOD;
    	}
    	cout<<500000004LL*ans%MOD;
    	return 0;
    }
    
  • 相关阅读:
    WebRTC中的NetEQ
    VoIP基本原理
    NetEQ主要文件简介
    声纹识别
    杂记(2019.04.13)
    概率论基础复习
    机器学习复习:模型评估指标
    传统机器学习算法复习:逻辑回归、因子分解机和梯度提升树
    Tensorflow中循环神经网络及其Wrappers
    einsum:爱因斯坦求和约定
  • 原文地址:https://www.cnblogs.com/stoorz/p/14821796.html
Copyright © 2011-2022 走看看