Music Problem
 思路:
 常规思路:
 模数取 
    
     
      
       
        3600
       
      
      
       3600
      
     
    3600,很容易想到 
    
     
      
       
        T
       
       
        ∗
       
       
        n
       
       
        ∗
       
       
        3600
       
      
      
       T*n*3600
      
     
    T∗n∗3600 的做法,空间上优化第一维,但时间复杂度太大
 数学优化:
 题解有人讲到抽屉原理:一个由 
    
     
      
       
        n
       
      
      
       n
      
     
    n 个数组成的数列 一定能找出若干个连续的数使它们之和能被 
    
     
      
       
        n
       
      
      
       n
      
     
    n 整除。特判掉 
    
     
      
       
        n
       
       
        >
       
       
        =
       
       
        3600
       
      
      
       n>=3600
      
     
    n>=3600 的情况,常规思路就可以通过了,我直呼 
    
     
      
       
        N
       
       
        B
       
      
      
       NB
      
     
    NB,不愧是清华的大佬
 code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 1e5 + 9;
const int mod = 3600;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int f[2][4000];
void work()
{
	cin >> n;
	if(n >= 3600){
        for(int i = 1, x; i <= n; ++i) cin >> x;// 这里要读完再输出,不然会wa
        cout << "YES" << endl;return;
    }
	for(int i = 0; i <= mod; ++i)
		for(int j = 0; j < 2; ++j)
			f[j][i] = 0;
	int op = 1;
	for(int i = 1, x; i <= n; ++i, op ^= 1){
		cin >> x;
		x %= mod;
		f[op][x] = 1;
		for(int j = mod - 1; j >= 0; --j){
			f[op][j] = max(f[op][j], f[op^1][j]);
			int k = (x + j) % mod;
			f[op][k] = max(f[op][k], f[op^1][j]);
		}
	}
	cout << (f[op^1][0] ? "YES" : "NO") << endl;
}
int main()
{
	ios::sync_with_stdio(0);
	int TT;cin>>TT;while(TT--)
	work();
	return 0;
}
二进制优化思路:
 把 
    
     
      
       
        
         a
        
        
         i
        
       
       
         
       
       
        %
       
       
         
       
       
        m
       
       
        o
       
       
        d
       
      
      
       a_i \ \% \ mod
      
     
    ai % mod 分成 
    
     
      
       
        m
       
       
        o
       
       
        d
       
      
      
       mod
      
     
    mod 组,然后一组有 
    
     
      
       
        
         c
        
        
         i
        
       
      
      
       c_i
      
     
    ci 个数,然后类似多组背包二进制优化的方法,可以很快的通过,很好用的优化思路,可以直接莽这个方法
 code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 1e5 + 9;
const int mod = 3600;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
int f[2][4000];
int cnt[4000];
void work()
{
	cin >> n;
	for(int i = 0; i < mod; ++i)
		for(int j = 0; j < 2; ++j)
			f[j][i] = 0;
	for(int i = 0; i < mod; ++i) cnt[i] = 0;
	for(int i = 1, x; i <= n; ++i) cin >> x, cnt[x%mod]++;
	if(cnt[0]){// 速度大幅提升主要是因为这个
		cout << "YES\n";return;
	}
	int op = 1;
	for(int i = 1; i < mod; ++i){
		if(!cnt[i]) continue;
		vector <int> v;
		int c = cnt[i];
		for(int j = 1; j <= c; j <<= 1)
		{
			v.push_back(i * j % mod);
			c -= j;
		}
		if(c) v.push_back(i * c % mod);
		for(auto d : v)
		{
			f[op][d] = 1;
			for(int j = mod - 1; j >= 0; --j)
			{
				f[op][j] = max(f[op][j], f[op^1][j]);
				int k = (d + j) % mod;
				f[op][k] = max(f[op][k], f[op^1][j]);
			}
			op ^= 1;
		}
	}
	cout << (f[op^1][0] ? "YES" : "NO") << endl;
}
int main()
{
	ios::sync_with_stdio(0);
	int TT;cin>>TT;while(TT--)
	work();
	return 0;
}
betset优化:
 用 
    
     
      
       
        b
       
       
        i
       
       
        t
       
       
        s
       
       
        e
       
       
        t
       
      
      
       bitset
      
     
    bitset 实现这道题的神奇做法
 代码简洁且高效,就是稍微有点抽象
 
    
     
      
       
        S
       
       
        T
       
       
        L
       
      
      
       STL
      
     
    STL 
    
     
      
       
        N
       
       
        B
       
      
      
       NB
      
     
    NB
 code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 4e3 + 9;
const int mod = 3600;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
void work()
{
	cin >> n;
	bitset <maxn * 2> f;
	for(int i = 1, x; i <= n; ++i){
		cin >> x; x %= mod;
		f |= f << x | f >> (mod - x);
		f[x] = 1;
	}
	cout << (f[0] ? "YES" : "NO") << endl;
}
int main()
{
	ios::sync_with_stdio(0);
	int TT;cin>>TT;while(TT--)
	work();
	return 0;
}










