牛客练习赛41(B 666RPG)

版权声明:随意转载 https://blog.csdn.net/nuiniu/article/details/88093765

题目传送门

这里呢,用的方法是dp,俗话说的好"神用dp,人用暴力",但是呢,我都不会(白嫖大佬的代码)。


方法简介:

首先,先const 一个maxn=666*300+5;这里加5嘛,就只有防爆炸的作用,重要的是这个666*300,为什么要定义一个maxn呢,因为,我们要开一个4*maxn大的二维数组ans[2][maxn*2+5],那么为什么要开一个maxn大的数组呢?

因为,我们需要的一个足够大的数组来储存我们所有可能的结果。那么问题又来了,所有的可能结果包括到什么程度。变看代码,边看注释

#include<bits/stdc++.h>

using namespace std;

const int maxn=666*300+5;	//以maxn为分界线,代表小于maxn的为负数的结果,大于maxn为大于0的结果 
const int mod=1e8+7;
int cur=1;
int old=0;

int ans[2][maxn*2+5];
int a[maxn];

//取模并赋值。 
void mo(int &x,int y)
{
	x=(x+y)%mod;
}

int main()
{
	int n;
	int i,j;
	
	cin>>n;
	for(i=0;i<n;++i) cin>>a[i];
	
	 
	ans[cur][maxn]=1;   //这里是一切可能的开始,没看懂得先看下面的。
	
	for(i=0;i<n;++i)
	{
		swap(cur,old);						//滚动数组 
		fill(ans[cur],ans[cur]+maxn*2,0);	//初始化当前的所需要更新的数组 
		for(j=-maxn;j<=maxn;++j)
		{
			if(j!=-666) mo(ans[cur][maxn+j],ans[old][maxn-j]);	//这里表示操作B,便利所有的可能,即便是不需要的可能(比如我们上一次更新当前数组后的a[x]的值为0代表x这个结果在更新后,没有一个可能的值为x) 
			if(j-a[i]>=-maxn&&j-a[i]!=666) mo(ans[cur][maxn+j],ans[old][maxn+j-a[i]]);	//这里是操作A,原理同上 
		}
	}
	
	cout<<ans[cur][maxn-666]<<endl;
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/nuiniu/article/details/88093765