[Daily] 20200508

C题.[Codeforces 831C] Jury Marks //暴力枚举

题目连接

思路

复杂版:
b[1]肯定是要放入某个位置的,放到某个位置之后,按照a数组的特定顺序分别向前逆打分向后正打分,就会得到特定的按照a数组打每个分后应该公布的每个分值(设其为数组B),这时候如果b数组中的每个值在B数组中都存在,我们前面放置b[1]的这种方案就合法,这时向前逆打分过程中求出来的最初分值就是一个合法的最初分值
(逆打分的意思就是还原打分前的情况,即依次-a[i]。正打分就是继续打分,即依次+a[i])
所以做法就是枚举b[1]可以放的位置(1->k),然后从这个位置分别向前逆打分、向后正打分,判断按这个方案得到的B数组里是否包含b数组中所有数,如果是,就合法,如果合法且向前得到的最初分值没出现过,答案就+1

简洁版:
枚举放置b[1]的位置(1->k),向前向后模拟打分过程,从而推出b数组应有的(1->k)全貌,判断b数组中每个数是否都有出现,若是则合法,累计(注意对最初分值去重)。

//AC代码
#include<bits/stdc++.h>
using namespace std;
const int N=2007,M=8000000;
int k,n,a[N],b[N],ans;
bool f[2*M+7];
map<int,int>mp;
int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>k>>n;
	for(int i=1;i<=k;i++)cin>>a[i];
	for(int i=1;i<=n;i++)cin>>b[i],f[M+b[i]]=1;
	int pre,nxt,flag;
	for(int i=1;i<=k;i++){
		nxt=pre=b[1];flag=1;
		f[M+b[1]]=0;
		for(int j=i;j>1;j--){
			pre-=a[j];
			f[M+pre]=0;
		}
		pre-=a[1];
		for(int j=i+1;j<=k;j++){
			nxt+=a[j];
			f[M+nxt]=0;
		}
		for(int j=1;j<=n;j++){
			if(f[M+b[j]])flag=0;
			f[M+b[j]]=1;
		}
		if(flag&&mp.count(pre)==0){
			ans++;
			mp[pre]=1;
		}
	}
	cout<<ans;
	

猜你喜欢

转载自blog.csdn.net/qq_45530271/article/details/106006529