简单题(数论)

同一道题:小狗狗也AK了!

题面

两个长度为 K K K 的正整数数列 a a a b b b,满足 ∑ i = 1 K a i = N   ,   ∑ i = 1 K b i = M \sum_{i=1}^Ka_i=N~,~\sum_{i=1}^Kb_i=M i=1Kai=N , i=1Kbi=M,对于这两个数列,定义权值为 P = ∏ i = 1 K min ⁡ ( a i , b i ) P=\prod_{i=1}^K\min(a_i,b_i) P=i=1Kmin(ai,bi) 。求所有可能的数列的权值之和。答案对 998244353 998244353 998244353 取模。

T T T 组数据,每组数据给出 N , M , K N,M,K N,M,K

T ≤ 100 , 1 ≤ N , M , K ≤ 5 × 1 0 5 , K ≤ min ⁡ ( N , M ) T\leq 100,1\leq N,M,K\leq5\times10^5,K\leq\min(N,M) T100,1N,M,K5×105,Kmin(N,M)

题解

做一个转换:『权值』即为长度为 K K K 的正整数数列 c c c 的数量,满足 ∀ i ∈ [ 1 , K ]   ,   c i ≤ a i , c i ≤ b i \forall i\in[1,K]~,~c_i\leq a_i,c_i\leq b_i i[1,K] , ciai,cibi

我们反向求,先求 c c c 的数量,再求与之对应的 ( a , b ) (a,b) (a,b) 方案数。

假设我们确定了 c c c,我们可以令 a i = a i − c i   ,   b i = b i − c i a_i=a_i-c_i~,~b_i=b_i-c_i ai=aici , bi=bici ,然后 a , b a,b a,b 就成了长度为 K、总和分别为 N − ∑ c i N-\sum c_i Nci M − ∑ c i M-\sum c_i Mci 的自然数数列

因此,枚举 x = ∑ c i x=\sum c_i x=ci ,对应的 c c c 的数量为 C ( x − 1 , K − 1 ) C(x-1,K-1) C(x1,K1) a a a 的数量为 C ( M − x − 1 + K , K − 1 ) C(M-x-1+K,K-1) C(Mx1+K,K1) b b b 的数量为 C ( M − x − 1 + K , K − 1 ) C(M-x-1+K,K-1) C(Mx1+K,K1)

于是,答案为
∑ x = K min ⁡ ( N , M ) C ( x − 1 , K − 1 ) ⋅ C ( M − x − 1 + K , K − 1 ) ⋅ C ( M − x − 1 + K , K − 1 ) \sum_{x=K}^{\min(N,M)} C(x-1,K-1)\cdot C(M-x-1+K,K-1)\cdot C(M-x-1+K,K-1) x=Kmin(N,M)C(x1,K1)C(Mx1+K,K1)C(Mx1+K,K1)

CODE

很快啊

#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 500005
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define lowbit(x) (-(x):(x))
#define SI(x) set<x>::iterator
#define FI first
#define SE second
LL read() {
	LL f=1,x=0;char s = getchar();
	while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
	while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
	return f * x;
}
void putpos(LL x) {
	if(!x) return ;
	putpos(x/10); putchar('0'+(x%10));
}
void putnum(LL x) {
	if(!x) {putchar('0');return ;}
	if(x < 0) putchar('-'),x = -x;
	putpos(x);
}
void AIput(LL x,char c) {putnum(x);putchar(c);}

const int MOD = 998244353;
int n,m,s,o,k;
int fac[MAXN<<1],inv[MAXN<<1],invf[MAXN<<1];
int C(int n,int m) {
	if(m < 0 || m > n) return 0;
	return fac[n] *1ll* invf[n-m] % MOD * invf[m] % MOD;
}
int main() {
	freopen("easy.in","r",stdin);
	freopen("easy.out","w",stdout);
	fac[0]=fac[1]=inv[0]=inv[1]=invf[0]=invf[1]=1;
	for(int i = 2;i <= MAXN*2-5;i ++) {
		fac[i] = fac[i-1] *1ll* i % MOD;
		inv[i] = (MOD - inv[MOD%i]) *1ll* (MOD/i) % MOD;
		invf[i] = invf[i-1] *1ll* inv[i] % MOD;
	}
	
	int T = read();
	while(T --) {
		n = read();m = read();k = read();
		if(n > m) swap(n,m);
		int ans = 0;
		for(int i = k;i <= n;i ++) {
			int bs = C(i-1,k-1);
			int ct = C(n-i-1+k,k-1) *1ll* C(m-i-1+k,k-1) % MOD;
			(ans += bs*1ll*ct % MOD) %= MOD;
		}
		AIput(ans,'\n');
	}
	return 0;
}
posted @ 2021-09-07 17:46  DD_XYX  阅读(28)  评论(0编辑  收藏  举报