题解 P5369 【[PKUSC2018]最大前缀和】
一丶前言
为了方便,定义/说明一些东西:
若存在多个
所以
我们假设
但是这样只能拿到
那我们稍稍改一改就行了,我的方法是假设一个
则
三丶代码
#include<bits/stdc++.h>
#define inf 1e9
#define eps 1e-6
#define N 21
#define mod 998244353
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline ll read()
{
char ch=getchar();
ll s=0,w=1;
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
inline ll Z(ll x){return x>=mod?x-mod:x;}
ll sum[1<<N];ll f[1<<N][2],g[1<<N];
ll n,a[N];
int main()
{
n=read();
for(register ll i=1;i<=n;i++)a[i]=read();
for(register ll i=0;i<(1<<n);i++)
{
for(register ll j=1;j<=n;j++)
{
if(i&(1<<(j-1)))sum[i]=sum[i]+a[j];
}
}
for(register ll i=1;i<=n;i++)if(a[i]<0)f[1<<(i-1)][0]=1;else f[1<<(i-1)][1]=1;//初始化
for(register ll i=1;i<(1<<n);i++)
{
ll S=i;
for(register ll j=1;j<=n;j++)
{
if(S&(1<<(j-1)))continue;
ll T=S|(1<<(j-1));
if(sum[T]>=0)f[T][1]=Z(f[T][1]+f[S][1]);
else f[T][0]=Z(f[T][0]+f[S][1]);
}
}
g[0]=1;
for(register ll i=0;i<(1<<n);i++)
{
ll S=i;if(!g[S])continue;
for(register ll j=1;j<=n;j++)
{
if(S&(1<<(j-1)))continue;
ll T=S|(1<<(j-1));
if(sum[T]<0)g[T]=Z(g[T]+g[S]);
}
}
ll U=(1<<n)-1,ans=0;
for(register ll i=1;i<=U;i++)
{
ans=Z(ans+Z(sum[i]%mod+mod)*Z(f[i][0]+f[i][1])%mod*g[U^i]%mod);
}
printf("%lld\n",ans);
return 0;
}
/*
3
0 1 -2
*/
如果认为我这篇题解对你有帮助的可以给我点一下赞qwq。如果有任何疑问,或者认为我的题解有什么问题的话,请务必私信我,感激不尽!我会努力把我的题解写得最好的!