首页 > 其他分享 >Luogu 2791 幼儿园篮球题

Luogu 2791 幼儿园篮球题

时间:2023-07-20 21:36:23浏览次数:41  
标签:frac dbinom limits int Luogu sum 篮球 Bmatrix 2791

考虑枚举选出来 \(i\) 个没气的篮球,那么答案可以表示成:

\[\text{ans}=\frac{1}{\dbinom{n}{k}}\sum\limits_{i=0}^{k}\dbinom{m}{i}\dbinom{n-m}{k-i}i^L \]

注意到这里的组合数 \(\dbinom{n}{m}\) 在 \(n<m\) 或者 \(m<0\) 时无意义,直接当成 \(0\) 即可。

考虑普通幂转下降幂:

\[i^L=\sum\limits_{j=0}^L\begin{Bmatrix}L\\j\end{Bmatrix}i^{\underline j} \]

带入原式有:

\[\begin{aligned}\text{ans}&=\frac{1}{\dbinom{m}{k}}\sum\limits_{i=0}^k\dbinom{m}{i}\dbinom{n-m}{k-i}\sum\limits_{j=0}^L\begin{Bmatrix}L\\j\end{Bmatrix}i^{\underline j}\\&=\frac{1}{\dbinom{m}{k}}\sum\limits_{j=0}^L\begin{Bmatrix}L\\j\end{Bmatrix}\sum\limits_{i=0}^k\dbinom{m}{i}\dbinom{n-m}{k-i}i^{\underline j}\end{aligned} \]

根据经典组合恒等式:

\[\begin{aligned}\dbinom{m}{i}i^{\underline j}&=\frac{m!}{i!(m-i)!}\cdot \frac{i!}{(i-j)!}\\&=\frac{m!}{(m-i)!(i-j)!}\\&=\frac{(m-j)!}{(m-i)!(i-j)!}\cdot \frac{m!}{(m-j)!}\\&=\dbinom{m-j}{i-j}m^{\underline j}\end{aligned} \]

代入原式得:

\[\begin{aligned}\text{ans}&=\frac{1}{\dbinom{m}{k}}\sum\limits_{j=0}^L\begin{Bmatrix}L\\j\end{Bmatrix}\sum\limits_{i=0}^k\dbinom{n-m}{k-i}\dbinom{m-j}{i-j}m^{\underline j}\\&=\frac{1}{\dbinom{m}{k}}\sum\limits_{j=0}^L\begin{Bmatrix}L\\j\end{Bmatrix}m^{\underline j}\sum\limits_{i=0}^k\dbinom{n-m}{k-i}\dbinom{m-j}{i-j}\\&=\frac{1}{\dbinom{m}{k}}\sum\limits_{j=0}^L\begin{Bmatrix}L\\j\end{Bmatrix}m^{\underline j}\dbinom{n-j}{k-j}\end{aligned} \]

第三步运用了范德蒙德卷积

于是我们只需要求出第 \(L\) 行的斯特林数值,就可以通过 \(O(N)\) 预处理阶乘及其逆元,对于每个询问 \(O(L)\) 得出答案。

这是个经典 trick,通过二项式反演以及 NTT 可以 \(O(L\log L)\)求出,可以看 P5395 第二类斯特林数·行,这里不多赘述。

总复杂度 \(O(N+L(\log L+q))\)。

// Problem: P2791 幼儿园篮球题
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2791
// Memory Limit: 222 MB
// Time Limit: 1110 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;

namespace vbzIO {
    char ibuf[(1 << 20) + 1], *iS, *iT;
    #if ONLINE_JUDGE
    #define gh() (iS == iT ? iT = (iS = ibuf) + fread(ibuf, 1, (1 << 20) + 1, stdin), (iS == iT ? EOF : *iS++) : *iS++)
    #else
    #define gh() getchar()
    #endif
    #define mt make_tuple
    #define mp make_pair
    #define fi first
    #define se second
    #define pc putchar
    #define pb emplace_back
    #define ins insert
    #define era erase
    typedef tuple<int, int, int> tu3;
    typedef pair<int, int> pi;
    inline int rd() {
        char ch = gh();
        int x = 0;
        bool t = 0;
        while (ch < '0' || ch > '9') t |= ch == '-', ch = gh();
        while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gh();
        return t ? ~(x - 1) : x;
    }
    inline void wr(int x) {
        if (x < 0) {
            x = ~(x - 1);
            putchar('-');
        }
        if (x > 9)
            wr(x / 10);
        putchar(x % 10 + '0');
    }
}
using namespace vbzIO;

const int N = 2e5 + 200;
const int M = 2e7 + 200;
const int P = 998244353;
const int G = 114514;
int q, n, len = 1, lim, a[N << 2], b[N << 2], tr[N << 2], fac[M], ifac[M];

int qpow(int p, int q) {
	int res = 1;
	for (; q; q >>= 1, p = 1ll * p * p % P)
		if (q & 1) res = 1ll * res * p % P;
	return res;
}

const int iG = qpow(G, P - 2);

void init(int lim) {
	fac[0] = 1;
	for (int i = 1; i <= lim; i++) 
		fac[i] = 1ll * fac[i - 1] * i % P;
	ifac[lim] = qpow(fac[lim], P - 2) % P;
	for (int i = lim - 1; ~i; i--)
		ifac[i] = 1ll * ifac[i + 1] * (i + 1) % P;
}

int C(int n, int m) {
	if (n < m || m < 0) return 0;
	return 1ll * fac[n] * ifac[m] % P * ifac[n - m] % P;
}

void NTT(int *f, int op) {
	for (int i = 0; i < len; i++)
		if (i < tr[i]) swap(f[i], f[tr[i]]);
	for (int o = 2, k = 1; k < len; o <<= 1, k <<= 1) {
		int tg = qpow((~op) ? G : iG, (P - 1) / o);
		for (int i = 0; i < len; i += o) {
			for (int j = 0, w = 1; j < k; j++, w = 1ll * w * tg % P) {
				int x = f[i + j], y = 1ll * f[i + j + k] * w % P;
				f[i + j] = (x + y) % P, f[i + j + k] = (x - y + P) % P;
			}
		}
	}
	if (~op) return;
	int iv = qpow(len, P - 2);
	for (int i = 0; i < len; i++)
		f[i] = 1ll * f[i] * iv % P;
}

int main() {
	int t = max(rd(), rd());
	q = rd(), n = rd(), init(t);
	for (int i = 0, g = 1; i <= n; i++, g = P - g)
		a[i] = 1ll * g * ifac[i] % P, b[i] = 1ll * qpow(i, n) * ifac[i] % P;
	while (len <= (n << 1)) len <<= 1, lim++;
	for (int i = 0; i < len; i++) 
		tr[i] = (tr[i >> 1] >> 1) | ((i & 1) << (lim - 1)); 
	NTT(a, 1), NTT(b, 1);
	for (int i = 0; i < len; i++)
		a[i] = 1ll * a[i] * b[i] % P;
	NTT(a, -1);
	while (q--) {
		int x = rd(), y = rd(), z = rd();
		int res = 0;
		for (int i = 0; i <= min(min(n, x), min(y, z)); i++) 
			(res += 1ll * a[i] * fac[y] % P * ifac[y - i] % P * C(x - i, z - i) % P) %= P;
		wr(1ll * res * qpow(C(x, z), P - 2) % P), pc('\n');
	}
	return 0;
}

标签:frac,dbinom,limits,int,Luogu,sum,篮球,Bmatrix,2791
From: https://www.cnblogs.com/Ender32k/p/17569726.html

相关文章

  • Luogu 6821 PA2012 Tanie linie
    这里只讲加强版,这是严格弱化。结论是贪心。每次取出最大和连续子段,目前答案加上这个子段和,然后再把这个子段取反(相反数T),然后求整个过程答案的最大值。考虑费用流模型。对于\(i\len\),\(S\toi\)连边,\(i\toT\)连边,流量为\(1\)费用为\(0\);\(i\toi+1\)连边,流量为\(1\)费......
  • Luogu 5296 生成树计数
    好像有道题是求生成树权值和的和的,考虑\(\sum\limits_{T}\sum\limits_{e\inE(T)}w_e\)咋做。每条边给一个边权\(v_e(x)=1+w_ex\),然后跑矩阵树:\[\text{ans}=[x]\sum\limits_{T}\prod\limits_{e\inE(T)}v_e(x)\]受到来自神秘力量的启示,我们考虑类似上面这样构造边权。考虑......
  • Luogu 3412 仓鼠找sugar II
    你也许说得对,但我是真看不懂第一篇题解那个答案式子……预处理是差不多的。设\(f_u\)表示从\(u\tofa(u)\)的期望步数,\(g_u\)为\(fa(u)\tou\)的期望步数,\(d_u\)为\(u\)的度数。那么显然有:\[f_u=\frac{1}{d_u}\left(1+\sum\limits_{v\inson(u)}(1+f_v+f_u)\right)......
  • 【题解】Luogu[P3360] 偷天换日
    solution开题显然是个树形dp,只不过在树形dp上又增加了背包问题。我们不妨将每个走廊看成一个点,把交叉口看成边(当然也可以把交叉口看成点,不过写起来麻烦一些),于是就转化为了一棵二叉树。我们设\(f_{i,j}\)表示以\(i\)为根的子树内,花费了不超过\(j\)时间,能拿到的最大价值......
  • 【题解】Luogu[P2607] [ZJOI2008] 骑士
    题目说给定\(n\)个点\(n\)个关系,也就是\(n\)条边,显然是基环树,又因为没有规定一定连通,于是我们可以将题目简化为给定一个基环树森林,点有点权,相邻的两个点不能同时选,问最大点权和。part1我们先考虑如果没有环,只是树,该怎么做。这一部分很简单,令\(f_{i,0/1}\)表示以\(i\)......
  • [刷题笔记] Luogu P1168 中位数
    ProblemDescription题目描述非常简洁,不作解释。Solution题目要求对前奇数项求中位数?朴素的做法是暴力,但是范围1e5显然T。这里主要介绍一种堆顶堆的做法。堆顶堆是什么呢?我们不妨开两个堆,一个大根堆一个小根堆。动态维护中位数,初始令前1位的中位数为\(a_i\),遍历数组,若遇到比中......
  • 洛谷 Luogu P1038 [NOIP2003 提高组] 神经网络
    这题看着很吓人实则很简单。求输出层,正着求很麻烦,因为知不道谁连向这个点,所以可以反向建边,反着求。拓扑+dfs,时间复杂度\(\text{O(n+m)}\)#include<iostream>#include<cstdio>#include<queue>#defineN105#defineM(N*N/2+114)structE{intv,w;......
  • luogu-modle
    P3383【模板】线性筛素数https://blog.csdn.net/huang_miao_xin/article/details/51331710首先看一个关于质数分布的规律:大于等于5的质数一定和6的倍数相邻。例如5和7,11和13,17和19等等;在6的倍数相邻两侧并不是一定就是质数。证明:令x≥1,将大于等于5的自然数可表示成:[6x-1......
  • luogu0_entry
    新手场和普及场前6关新手场顺序与分支P1422小玉家的电费控制输出精度:cout.xxx();待查询P1089津津的储蓄计划注意int和float相乘,输出格式用"%d"数字会面目全非P1909买铅笔INT_MAX存在<limits.h>里,不加.h也不行循环P1035级数求和我写了一个求和的函数Sn(in......
  • luogu1_dfsbfs
    普及练习场知识点汇总:DFS、BFS、☆杨辉三角P1118USACO06FEB数字三角形☆求解的个数用深搜,求最优解用广搜。DFSP1219八皇后弱智一样的我,还建立NxN的矩阵来模拟。结果呢,检查(check)时要遍历整个棋盘,最终导致只能过部分。根本不用二维矩阵。dfs(i),因为传进来的i是行号,......