示例1
输入
3 3 2000 1000 3000 3 2000 3000 1600 2 5400 1800
输出
NO YES YES
题意:给你n个数,问你是否能选出若干个数使得数字的和为3600的倍数(至少选一个)。
思路:这道题的话,可以想到用背包来做,但是时间复杂度不太允许能轻松解决这道题。所以我简单学习了一下bitset优化背包的做法。bitset上面每个数代表这个数能不能被取到,首先先对所有的a[i]取模3600,这样的话,每个a[i]都在0-3599范围里。然后我们考虑每一个a[i]的时候,答案只可能增多或者不变,因此使用|或运算符就可以,但是我们还要特别考虑的是溢出问题,因为你可能向右右移了a[i]位之后溢出了,那么我们就在|上一个向左移3600位的结果即可。
关于bitset优化背包:https://www.cnblogs.com/chinacwj/p/8371578.html
AC代码:
#include <stdio.h>
#include <string>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
typedef long long ll;
const int maxx=100010;
const int mod=2333;
const int inf=0x3f3f3f3f;
const double eps=1e-8;
using namespace std;
template<class T>inline void read(T &res)//快速读入模板
{
char c;
T flag=1;
while((c=getchar())<'0'||c>'9')
if(c=='-')
flag=-1;
res=c-'0';
while((c=getchar())>='0'&&c<='9')
res=res*10+c-'0';
res*=flag;
}
int a[maxx];
int main()
{
int t;
read(t);
while(t--)
{
int n;
read(n);
for(int i=1; i<=n; i++)
{
read(a[i]);
a[i]%=3600;
}
bitset<7210>dp;
for(int i=1; i<=n; i++)
{
dp|=(dp<<a[i])|(dp<<a[i]>>3600);
dp[a[i]]=1;
}
if(dp[0])
printf("YES\n");
else
printf("NO\n");
}
return 0;
}