Negative and Positive (NP)
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1161 Accepted Submission(s): 59
问题描述
给定一个数组 (a0,a1,a2,⋯an−1) 和一个整数 K , 请来判断一下是否存在二元组 (i,j)(0≤i≤j<n) 使得 NP−sum(i,j) 刚好为 K 。这里 NP−sum(i,j)=ai−ai+1+ai+2+⋯+(−1)j−iaj 。
输入描述
多组测试数据。在文件的第一行给出一个 T ,表示有 T 组数据。 在接下来的 2∗T 行里,将会给出每一组数据。 每一组数据占两行,第一行包含 n 和 K 。 第二行包含 (a0,a1,a2,⋯an−1) 以一个空格分开。 [参数说明] 所有输入均为整数。 0<T≤25,1≤n≤1000000,−1000000000≤ai≤1000000000,−1000000000≤K≤1000000000
输出描述
对于每一个数据,输出占一行,输出格式是Case #id: ans,这儿id是数据编号,从1开始,ans是根据是否找到满足的二元组而定为“Yes.” 或 “No.” (不包含引号) 看样例可以获得更多的信息。
输入样例
2 1 1 1 2 1 -1 0
输出样例
Case #1: Yes. Case #2: No.
Hint
如果数据比较多,建议使用快速读入。#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> using namespace std; const int maxn=1000007; typedef long long ll; const int inf=INT_MAX; template<class T>inline T read(T&x) { char c; while((c=getchar())<=32); bool f=false; if(c=='-')f=true,c=getchar(); for(x=0;c>32;c=getchar())x=x*10+c-'0'; if(f)x=-x; return x; } int a[maxn],n; ll k; struct hash { int head[maxn],next[maxn],size; ll state[maxn]; void init() { size=0; memset(head,-1,sizeof(head)); } bool check(ll val) { int h=(val%maxn+maxn)%maxn; for(int i=head[h];~i;i=next[i]) if(val==state[i])return true; return false; } bool insert(ll val) { int h=(val%maxn+maxn)%maxn; for(int i=head[h];~i;i=next[i]) { if(val==next[i])return true; } state[size]=val; next[size]=head[h]; head[h]=size++; return false; } }h[2]; bool solve() { h[0].init(); h[1].init(); h[0].insert(0); h[1].insert(0); ll sum = 0; for(int i = n - 1; i >= 0; --i) { if(i&1) sum -= a[i]; else sum += a[i]; if(i%2 == 0) { if(h[0].check(sum-k)) return 1; } else { if(h[1].check(-sum-k)) return 1; } h[0].insert(sum); h[1].insert(-sum); } return 0; } int main() { int m,i,j,t; int T; read(T); int cas=1; while(T--) { read(n); read(k); for(i=0;i<n;i++) read(a[i]); printf("Case #%d: ",cas++); if(solve())puts("Yes."); else puts("No."); } return 0; }