LOJ6433 PKUSC2018 最大前缀和

喵哒 好不容易想出来结果被题面坑了呜呜呜

j=1!!!! 前缀和不能为空!!!

喵哒= =

所以我们可以想到 对于没选的后缀 肯定是所有前缀和都要<=0 不然的话就可以加上比原来更优 然后这个很明显可以dp哒

然后 对于前面的 我们可以发现我们倒着插入就是只要插入前>0的话就是可以转移哒 <0的话显然不选更优

那么分别进行dp 合并即可 注意最后要(ans+wph)%wph

呜呜呜辣鸡PKU全是细节呜呜呜

//Love and Freedom.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 20021225
#define ll long long
#define mxn (1<<20)
#define wph 998244353
using namespace std;

int f[mxn],g[mxn];
int a[20],n;
int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)	scanf("%d",&a[i]);
	int top = 1<<n; top--; ll sum,ans; sum=ans=0;
	g[0] = 1;
	for(int i=0;i<=top;i++)
	{
		sum = 0;
		for(int j=0;j<n;j++)
			if(i>>j&1)	sum+=a[j];
		for(int j=0;j<n;j++)
			if(!(i>>j&1))	if(sum+a[j]<=0)
				g[i|(1<<j)]	= (g[i|(1<<j)] + g[i])%wph;
	}
	for(int i=0;i<n;i++)	f[1<<i] = 1;
	for(int i=0;i<=top;i++)
	{
		sum = 0;
		for(int j=0;j<n;j++)
			if(i>>j&1)	sum+=a[j];
		//if(sum < 0)	continue;
		sum %= wph;
		ans += (ll)f[i]*g[top^i]%wph*sum%wph;
		//printf("%d\n",ans);
		ans %= wph;
		for(int j=0;j<n;j++)
			if(!(i>>j&1))	if(sum>0)
				f[i|(1<<j)]	= (f[i|(1<<j)] + f[i])%wph;
	}
	printf("%lld\n",(ans+wph)%wph);
	return 0;
}
/**
3
1 -1 1
*/

 

posted @ 2019-01-10 08:31  寒雨微凝  阅读(118)  评论(0编辑  收藏  举报