jzoj5945

這題是均分紙牌求方案數
我們可以分2種情況討論:
1.當前面部分的平均值>=現在我們要的值
那麼我們可以把所有牌都放到第i個點,現在若有k張牌,則要把k−i∗avek-i*avekiave張牌放到後面
對答案的貢獻為c(a[i],k−i∗ave)c(a[i],k-i*ave)c(a[i],kiave),要更新現在的元素值
2.當前面部分平均值<現在我們要的值
那麼我們可以從後面抓i∗ave−ki*ave-kiavek張牌
由於我們要讓所有部分有aveaveave張牌,所以我們後面需要有ave+i∗ave−kave+i*ave-kave+iavek張牌,才可以讓抓牌後這部分有aveaveave張牌
所以對答案的貢獻為c((i+1)∗ave−s[i],i∗ave−s[i])c((i+1)*ave-s[i],i*ave-s[i])c((i+1)aves[i],iaves[i])

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mo 998244353ll
ll t,n,a[1010],jc[1000010],ijc[1000010],s[1010];
ll qp(ll x,ll y){
	ll r=1;
	while(y){
		if(y&1)r=r*x%mo;
		x=x*x%mo;
		y>>=1;
	}
	return r;
}
void get(){
	jc[0]=1;
	for(ll i=1;i<=1000005;i++)
		jc[i]=jc[i-1]*i%mo;
	ijc[0]=1;
	for(ll i=1;i<=1000005;i++)
		ijc[i]=ijc[i-1]*qp(i,mo-2)%mo; 
}
ll c(ll x,ll y){
	return jc[x]*ijc[x-y]%mo*ijc[y]%mo;
}
int main(){
	freopen("gwent.in","r",stdin);
	freopen("gwent.out","w",stdout);
	scanf("%lld",&t);
	get();
	while(t--){
		scanf("%lld",&n);
		for(ll i=1;i<=n;i++)
			scanf("%lld",&a[i]);
		for(ll i=1;i<=n;i++)
			s[i]=s[i-1]+a[i];
		ll k=s[n]/n,ans=1;
		for(ll i=1;i<=n;i++){
			ll va=s[i]-k*i;
			if(va>=0){
				ans=ans*c(a[i],va)%mo;
				a[i]-=va;
				a[i+1]+=va;
			}
			else ans=ans*c(-va+k,-va)%mo;
		}
		printf("%lld\n",ans);
	}
}

转载于:https://www.cnblogs.com/rilisoft/p/10385229.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值