• [题解] [AGC 001 E] BBQ Hard


    题面

    题解

    先化简一下

    [displaystyle egin{aligned}&sum_{i = 1}^{n}sum_{j = i + 1}^{n}inom{a_i+a_j+b_i+b_j}{a_i+a_j}\=&frac{sum_{i = 1}^{n}sum_{j = 1}^{n}inom{a_i+a_j+b_i+b_j}{a_i+a_j}-sum_{i = 1}^{n}inom{2*a_i+2*b_i}{2*a_i}}{2}end{aligned} ]

    后面那个可以 (O(n)) 地算出来

    所以现在的问题就是前面这个东西怎么算

    仔细观察一下括号内的东西, 发现可以把他变成网格图计数

    就是 ((0, 0))((a_i + a_j, b_i + b_j)) 的路径数

    再换一下, 变成从 ((-a_i, -b_i))((a_j, b_j)) 的方案数

    考虑到 (a)(b) 都很小, 你网格图跑一遍路径和就完了

    Code

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    const int mod = 1000000007;
    const int N = 4005;
    const int M = 8000; 
    using namespace std;
     
    int f[N + 505][N + 505], a[200005], b[200005], fac[M << 1], inv[M << 1], base, ans, n; 
     
    template < typename T >
    inline T read()
    {
    	T x = 0, w = 1; char c = getchar();
    	while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
    	while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return x * w; 
    }
     
    int fpow(int x, int y)
    {
    	int res = 1;
    	while(y)
    	{
    		if(y & 1)
    			res = 1ll * res * x % mod;
    		x = 1ll * x * x % mod;
    		y >>= 1; 
    	}
    	return res; 
    }
     
    int C(int n, int m) { return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod; }
     
    int main()
    {
    	n = read <int> (), base = 2002;
    	for(int i = (fac[0] = 1); i <= M; i++)
    		fac[i] = 1ll * fac[i - 1] * i % mod;
    	inv[M] = fpow(fac[M], mod - 2);
    	for(int i = M - 1; i >= 0; i--)
    		inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
    	for(int i = 1; i <= n; i++)
    	{
    		a[i] = read <int> (), b[i] = read <int> ();
    		f[base - a[i]][base - b[i]]++; 
    	}
    	for(int i = 1; i <= base + 2000; i++)
    		for(int j = 1; j <= base + 2000; j++)
    			f[i][j] = (1ll * f[i][j] + f[i - 1][j] + f[i][j - 1]) % mod;
    	for(int i = 1; i <= n; i++)
    	{
    		ans = (1ll * ans + f[base + a[i]][base + b[i]]) % mod;
    		ans = (1ll * ans - C(2 * a[i] + 2 * b[i], 2 * a[i])) % mod; 
    	}
    	ans = (ans + mod) % mod;
    	ans = 1ll * ans * 500000004 % mod;
    	printf("%d
    ", ans); 
    	return 0; 
    }
    
  • 相关阅读:
    C++实现多项式曲线拟合--polyfit-超定方程
    C# XmlDocument操作XML
    C#下使用XmlDocument详解
    前端常见的9种设计模式
    前端常用的设计模式
    前端需要了解的9种设计模式
    TCP协议详解
    请UI小姐姐喝了一杯奶茶要来的网站
    nodemon 基本配置与使用
    wireshark抓包新手使用教程
  • 原文地址:https://www.cnblogs.com/ztlztl/p/12187834.html
Copyright © 2020-2023  润新知