P6059 [加油武汉]居家隔离 题解
题目链接
P6059 [加油武汉]居家隔离
Solution
以下分析时,默认轮数为
先分析一下算法大概的框架。
时间复杂度要求是
然后我们注意到决策中有一个很重要的分解点
我们通过期望的定义来计算这道题,即
这道题我们可以看做是对原序列的所有排列来求答案,所以方案数为
当 k\in[m,n-1] 时。
最后的答案显然是
考虑答案是
因为前
考虑
由于
可以发现贡献与
当 k=n 时。
这时显然不存在
我们假设答案是
考虑这选出来的
由于默认
由于对每一个
综上,我们得到了一个
Code
#include<bits/stdc++.h>
#define del(a,i) memset(a,i,sizeof(a))
#define ll long long
#define inl inline
#define il inl void
#define it inl int
#define ill inl ll
#define re register
#define ri re int
#define rl re ll
#define INF 0x3f3f3f3f
#define lowbit(x) (x&(-x))
#define mid ((l+r)>>1)
using namespace std;
template<class T>il read(T &x){
x=0;int f=1;char k=getchar();
for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
for(;k>='0'&&k<='9';k=getchar()) x=x*10+k-'0';
x*=f;
}
template<class T>il _print(T x){
if(x>9) _print(x/10);
putchar(x%10+'0');
}
template<class T>il print(T x){
if(x<0) putchar('-'),x=-x;
_print(x);
}
it qpow(int x,int k,int mod){
int res=1,bas=x;
while(k){
if(k&1) res=1ll*res*bas%mod;
bas=1ll*bas*bas%mod,k>>=1;
}
return res;
}
const int N = 1e3+5,mod = 998244353;
int n,fac[N],ifac[N],val[N],sum[N];
it add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
it mul(int x,int y){return 1ll*x*y%mod;}
il inc(int &x,int y){x=add(x,y);}
it C(int n,int m){return m>n?0:mul(mul(ifac[m],ifac[n-m]),fac[n]);}
il Solve(int m){
int res=0,div=fac[n];
for(ri i=m;i<n;++i){
int tval=add(sum[n],mod-sum[i]);
tval=mul(tval,C(i-1,m-1));
tval=mul(tval,C(n-m,i-m));
tval=mul(tval,fac[m]);
tval=mul(tval,fac[i-m]);
tval=mul(tval,fac[n-i-1]);
inc(res,tval);
}
int tval=mul(C(n-2,m-1),fac[m]);
tval=mul(tval,sum[n-1]);
tval=mul(tval,fac[n-m-1]);
inc(res,tval);
print(mul(res,qpow(div,mod-2,mod))),putchar(' ');
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n),fac[0]=1;
for(ri i=1;i<=n;++i) fac[i]=mul(fac[i-1],i);
ifac[n]=qpow(fac[n],mod-2,mod);
for(ri i=n-1;i>=0;--i) ifac[i]=mul(ifac[i+1],i+1);
for(ri i=1;i<=n;++i) read(val[i]);
sort(val+1,val+1+n);
for(ri i=1;i<=n;++i) sum[i]=add(sum[i-1],val[i]);
for(ri i=1;i<n;++i)
Solve(i);
return 0;
}