想了几天都只想到一半,看大佬们的题解(看完大佬的题解我又要开始转变代码风格了)还看了很久,如果我现场做估计已经跪掉了。
首先,考虑对于答案的计算。
设
表示第
种排列的最大前缀和,由于一共有
个排列,所以最后的答案就应该为:
所以我们最后的结果其实就是所有排列的最大前缀和之和。
接着,我们来考虑对于每一个排列,最大前缀和出现的位置。假设最大前缀和的前缀的最后一个数的位置为 ,那么一定 之后的数的前缀之和都要 ,不然就可以替换掉 使得最大前缀和可以更大。所以我们就把每一个排列分为两个部分来考虑,分割点就是 。
表示 这个状态的数值之和。
表示在 这个状态下最大前缀和为 的方案数,转移为:
表示在 这个状态下的最大前缀和都 的方案数,转移为:
于是我们就得到了最后的答案:
#include <bits/stdc++.h>
#define For(I,L,R) for(I=(L);I<=(R);I++)
using namespace std;
inline int Read(){
int X=0;char CH=getchar();bool F=0;
while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
return F?-X:X;
}
const int Mod=998244353;
int F[1<<20],G[1<<20];
int N,T,Ans,A[1<<20],Sum[1<<20];
#define LowBit(X) (X&(-X))
#define Add(X,Y) if(((X)+=(Y))>=Mod) (X)-=Mod
int main(){
int I,J,K;
N=Read();T=(1<<N)-1;
For(I,0,N-1) F[1<<I]=1,A[1<<I]=Read();
For(I,0,T) Sum[I]=Sum[I^LowBit(I)]+A[LowBit(I)];
For(I,0,T) if(Sum[I]>0)
For(J,0,N-1) if(!((I>>J)&1))
Add(F[I|(1<<J)],F[I]);
G[0]=1;
For(I,0,T) if(Sum[I]<=0)
For(J,0,N-1) if((I>>J)&1)
Add(G[I],G[I^(1<<J)]);
For(I,0,T)
Add(Ans,(1ll*(Sum[I]+Mod)*F[I]%Mod*G[T^I]%Mod));
printf("%d\n",Ans);
return 0;
}