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;