NC13885 Music Problem
和简单瞎搞题 类似
状态表示:\(f[i][j]\) 表示前\(i\)个数能组成的模3600的数,\(f\)只有0、1两种状态
答案:判断\(f[n][0]\)是否为真即可
时间复杂度:\(O(T*n*3600)\),显然无法接受
优化:将bool数组替换成bitset
const int N=1e5+10;
int a[N];
bitset<7200> f[2];
int n;
int main()
{
int T;
cin>>T;
while(T--)
{
f[0].reset();
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
{
f[i&1]=f[i-1&1];
f[i&1] |= f[i-1&1]<<(a[i]%3600) | (f[i-1&1]<<(a[i]%3600)>>3600);
f[i&1][a[i]%3600]=1;//一定要放在或操作后面,若对第i个先置1再或操作转移,相当于加上了第i个物品放两次的状态
}
if(f[n&1][0]) puts("YES");
else puts("NO");
}
//system("pause");
}
继续对滚动数组优化:
const int N=1e5+10;
int a[N];
bitset<7200> f;
int n;
int main()
{
int T;
cin>>T;
while(T--)
{
f.reset();
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
{
f|=f<<(a[i]%3600) | (f<<(a[i]%3600)>>3600);
f[a[i]%3600]=1;
}
if(f[0]) puts("YES");
else puts("NO");
}
//system("pause");
}