求助状压DP/kel
查看原帖
求助状压DP/kel
247269
MSqwq楼主2021/5/12 21:43
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#define ll long long
using namespace std;
const int N=25,M=1<<25;
const int mod=998244353;
int n,tot;
ll ans;
ll a[N],sum[M],g[M],f[M];
void fan()
{
	for(int i=0;i<=n;i++)a[i]*=-1;
	for(int i=0;i<=tot;i++)sum[i]*=-1;	
}
int main()
{
	scanf("%d",&n);
	tot=(1<<n)-1,g[0]=f[0]=1;
	for(int i=0;i<n;i++)scanf("%lld",&a[i]);
	for(int i=0;i<=tot;i++)
	{
		for(int j=0;j<n;j++)
			if(i&(1<<j))sum[i]=(sum[i]+a[j])%mod;
	}
	for(int i=1;i<=tot;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(i&(1<<j)&&sum[i^(1<<j)]+a[j]>=0)
				f[i]=(f[i]+f[i^(1<<j)])%mod;
		}
	}
	
	fan();
	
	for(int i=1;i<=tot;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(i&(1<<j)&&sum[i^(1<<j)]+a[j]>0)
				g[i]=(g[i]+g[i^(1<<j)])%mod;
		}
	}
	
	fan();
	
	for(int i=0;i<n;i++)
	{
		if(a[i]<0)
		{
			//f[1<<j]=1;
			for(int j=0;j<=tot;j++)
			{
				if(j&(1<<i)==0)
				{
					if(sum[j]<0||sum[j]+a[i]>0)continue;
					int x=tot^j^(1<<i);
					ans=(ans%mod+(a[i]+sum[j])%mod*f[j]%mod*g[x]%mod+mod)%mod;
				}
			}
		}
	}
	for(int i=0;i<=tot;i++)ans=(ans+f[i]%mod*sum[i]%mod*g[tot^i]+mod)%mod;
	printf("%lld",ans);
}
2021/5/12 21:43
加载中...