【JZOJ 省选模拟】6699. 这钵和餐厅配合的不是很好

题目

Description
在这里插入图片描述

Input
第⼀⾏⼀个n ,代表菜的个数。

接下来⼀⾏ n个正整数 ,代表第 i个菜的下饭度。

Output
⼀⾏⼀个数表⽰所有的上菜顺序,它们的下饭度之和对998244353取模的结果。

Sample Input
输⼊样例1:
3
1 2 2

输⼊样例2:
5
11 63 7 15 26

输⼊样例3:
15
2 2 1 2 1 1 2 2 1 2 1 2 2 2 1

Sample Output
输出样例1:
765320671

输出样例2:
19890604

输出样例3:
272794731

Data Constraint
对于所有数据, 1<=n<=200,1<=ai <=1000;

Hint
在这里插入图片描述

思路

在这里插入图片描述

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=207,M=N*1007,mod=998244353;
int n;
ll ans,invA=1,sum[N],a[N],inv[M],pre[M],f[M],g[M];
ll power(ll x,ll t)
{
	ll b=1;
	while(t)
	{
		if(t&1) b=b*x%mod;
		x=x*x%mod; t>>=1;
	}
	return b;
}
int main()
{
	freopen("restaurant.in","r",stdin); freopen("restaurant.out","w",stdout);
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i],invA=invA*a[i]%mod;
	invA=power(invA,mod-2);
	inv[0]=inv[1]=1; 
	for(int i=2; i<=sum[n]; i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
	pre[0]=1;
	for(int i=1; i<=n; i++) for(int j=sum[i-1]; j>=0; j--) pre[j+a[i]]=(pre[j+a[i]]-pre[j]+mod)%mod;
	for(int i=1; i<=n; i++)
	{
		memset(f,0,sizeof(f));
		for(int j=0; j<=sum[n]; j++) g[j]=pre[j];
		for(int j=sum[n]; j>=a[i]; j--) f[j-a[i]]=(f[j-a[i]]-g[j]+mod)%mod,g[j-a[i]]=(g[j-a[i]]+g[j])%mod;
		for(int j=0; j<=sum[n]; j++) ans=(ans+f[j]*a[i]%mod*a[i]%mod*invA%mod*inv[j+a[i]]%mod)%mod;
	}
	printf("%lld",ans);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章