题意:
分析:
最开始想到的是鸽巢原理,即当 (ngeq 3600) 时,必定存在一段连续的数之和为 (3600) 的倍数。但是当 (n<3600) 时,就不知道怎么处理了。
看了别人的代码,才发现是 (dp)。另外发现还有一种做法,借助 (bitset) 来枚举,判断哪些数是可以得到的,(bt[i]) 表示 (i) 可以得到。
对于当前枚举到的数 (a[i]),如果直接枚举其他数,来得到新的数,复杂度就会比较高。
这时,采用 (bitset),借助位移来直接处理。
(bt<<a[i]) 表示所有数同时加上 (a[i]) 所得到的数,但可能会溢出 (3600) 的范围,所以要用 (bt>>(3600-a[i])) 来表示,最后两者相或,统计结果,然后或到 (bt) 上。接着把 (bt[a[i]]) 赋 (1)。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N=3605;
const int maxn=1e5+5;
bitset<N>bt;
int a[maxn];
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
bt.reset();
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]%=3600;
}
if(n>=3600)
printf("YES
");
else
{
for(int i=1;i<=n;i++)
{
bt|=((bt<<a[i])|(bt>>(3600-a[i])));
bt[a[i]]=1;
}
if(bt[0])
printf("YES
");
else
printf("NO
");
}
}
return 0;
}