题目大意
题目大意
定义一种自然数下的二元运算「月球异或」(记作 ⊛ \circledast ⊛ ):将两个自然数转换为三进制后,对每一位分别相加并对 3 3 3 取模(即三进制下的不进位加法 )。例如 8 ( 10 ) ⊛ 1 6 ( 10 ) = 02 2 ( 3 ) ⊛ 12 1 ( 3 ) = 11 0 ( 3 ) = 1 2 ( 10 ) 8_{(10)} \circledast 16_{(10)} = 022_{(3)} \circledast 121_{(3)} = 110_{(3)} = 12_{(10)} 8 ( 1 0 ) ⊛ 1 6 ( 1 0 ) = 0 2 2 ( 3 ) ⊛ 1 2 1 ( 3 ) = 1 1 0 ( 3 ) = 1 2 ( 1 0 ) 。
现给定一个长度为 N N N 的自然数序列 v 1 , v 2 , … , v N v_1, v_2, \dots, v_N v 1 , v 2 , … , v N 。你可以对序列中的任意元素 v i v_i v i 执行以下两种操作任意次 (包含零次):
v i ← v i ⊛ v i v_i \leftarrow v_i \circledast v_i v i ← v i ⊛ v i
v i ← 0 v_i \leftarrow 0 v i ← 0
有 Q Q Q 次独立的询问,每次询问给出一个自然数 s s s 。对于每次询问,你需要判断能否通过若干次上述操作,使得序列全部元素的「月球异或」和等于 s s s (即 v 1 ⊛ v 2 ⊛ ⋯ ⊛ v N = s v_1 \circledast v_2 \circledast \dots \circledast v_N = s v 1 ⊛ v 2 ⊛ ⋯ ⊛ v N = s )。
数据范围
测试组数 :1 ≤ T ≤ 100000 1 \le T \le 100000 1 ≤ T ≤ 1 0 0 0 0 0
序列长度与询问次数 :1 ≤ N , Q ≤ 1 0 6 1 \le N, Q \le 10^6 1 ≤ N , Q ≤ 1 0 6 ,且所有测试组的 ∑ N , ∑ Q ≤ 2 × 1 0 6 \sum N, \sum Q \le 2 \times 10^6 ∑ N , ∑ Q ≤ 2 × 1 0 6
序列元素与询问值 :0 ≤ v i , s i ≤ 1 0 18 0 \le v_i, s_i \le 10^{18} 0 ≤ v i , s i ≤ 1 0 1 8
样例数据
输入 :
1 2 3 4 5 6 7 8 9 10 3 1 4 1 0 1 2 3 3 5 0 5 10 4 5 6 7 8 3 6 8 16 32 12 17 57 41 4 44
输出 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Yes Yes Yes No No Yes No Yes No Yes No Yes No Yes Yes
样例解释
以第一组样例为例:
此时 N = 1 , Q = 4 N=1, Q=4 N = 1 , Q = 4 ,序列只包含一个元素 v 1 = 1 v_1 = 1 v 1 = 1 。
四次询问的值分别为 s = 0 , 1 , 2 , 3 s = 0, 1, 2, 3 s = 0 , 1 , 2 , 3 。
对于 v 1 = 1 v_1 = 1 v 1 = 1 (三进制表示为 0 1 ( 3 ) 01_{(3)} 0 1 ( 3 ) ),它可能变化得到的状态有:
因为操作本质上是对三进制的每一位独立进行乘法并对 3 3 3 取模,或者直接置零,所以原本为 0 0 0 的高位(如 3 1 3^1 3 1 对应的位)永远不可能变成非 0 0 0 值。
目标 s = 3 s=3 s = 3 在三进制下表示为 1 0 ( 3 ) 10_{(3)} 1 0 ( 3 ) ,其第 1 1 1 位(对应数值 3 3 3 )的值为 1 1 1 ,而 v 1 v_1 v 1 无论怎么操作在第 1 1 1 位上永远是 0 0 0 ,因此永远无法得到 3 3 3 。
最终对于 0 , 1 , 2 , 3 0, 1, 2, 3 0 , 1 , 2 , 3 的询问,前三个可以得到,后一个无法得到,分别输出 Yes、Yes、Yes、No。
思路讲解
其实,不难发现,我们其实就是要看一个数字能不能用我们的这个三进制异或线性基表示出来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 class modn_XOR_base { private : vector<ll> base; vector<vector<ll>> mat; ll mod; ll power (ll a, ll b) const { ll res = 1 ; a %= mod; while (b > 0 ) { if (b & 1 ) res = (res * a) % mod; a = (a * a) % mod; b >>= 1 ; } return res; } ll modInverse (ll n) const { return power (n, mod - 2 ); } public : modn_XOR_base (ll Mod) { mod = Mod; base.assign (64 , 0 ); mat.assign (64 , vector <ll>(64 , 0 )); } bool insert (ll x) { ll orig_x = x; vector<ll> v (64 , 0 ) ; for (int i = 0 ; i < 64 ; ++i) { v[i] = x % mod; x /= mod; } for (int i = 63 ; i >= 0 ; --i) { if (v[i] == 0 ) continue ; if (base[i] == 0 ) { ll inv = modInverse (v[i]); for (int j = 0 ; j <= i; ++j) { mat[i][j] = (v[j] * inv) % mod; } base[i] = orig_x; return true ; } ll k = v[i]; for (int j = 0 ; j <= i; ++j) { v[j] = (v[j] - k * mat[i][j]) % mod; if (v[j] < 0 ) v[j] += mod; } } return false ; } bool query (ll x) const { vector<ll> v (64 , 0 ) ; for (int i = 0 ; i < 64 ; ++i) { v[i] = x % mod; x /= mod; } for (int i = 63 ; i >= 0 ; --i) { if (v[i] == 0 ) continue ; if (base[i] == 0 ) return false ; ll k = v[i]; for (int j = 0 ; j <= i; ++j) { v[j] = (v[j] - k * mat[i][j]) % mod; if (v[j] < 0 ) v[j] += mod; } } return true ; } }; int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); int T; cin >> T; while (T--) { modn_XOR_base base (3 ) ; ll N, Q; cin >> N >> Q; for (int i = 0 ; i < N; ++i){ ll x; cin >> x; base.insert (x); } for (int i = 0 ; i < Q; ++i){ ll t; cin >> t; cout << (base.query (t) ? "Yes\n" : "No\n" ); } } return 0 ; }
AC代码
AC
https://acm.hdu.edu.cn/contest/view-code?cid=1199&rid=7820&from=rank
源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 #include <bits/stdc++.h> using namespace std;typedef long long ll;class modn_XOR_base { private : vector<ll> base; vector<vector<ll>> mat; ll mod; ll power (ll a, ll b) const { ll res = 1 ; a %= mod; while (b > 0 ) { if (b & 1 ) res = (res * a) % mod; a = (a * a) % mod; b >>= 1 ; } return res; } ll modInverse (ll n) const { return power (n, mod - 2 ); } public : modn_XOR_base (ll Mod) { mod = Mod; base.assign (64 , 0 ); mat.assign (64 , vector <ll>(64 , 0 )); } bool insert (ll x) { ll orig_x = x; vector<ll> v (64 , 0 ) ; for (int i = 0 ; i < 64 ; ++i) { v[i] = x % mod; x /= mod; } for (int i = 63 ; i >= 0 ; --i) { if (v[i] == 0 ) continue ; if (base[i] == 0 ) { ll inv = modInverse (v[i]); for (int j = 0 ; j <= i; ++j) { mat[i][j] = (v[j] * inv) % mod; } base[i] = orig_x; return true ; } ll k = v[i]; for (int j = 0 ; j <= i; ++j) { v[j] = (v[j] - k * mat[i][j]) % mod; if (v[j] < 0 ) v[j] += mod; } } return false ; } bool query (ll x) const { vector<ll> v (64 , 0 ) ; for (int i = 0 ; i < 64 ; ++i) { v[i] = x % mod; x /= mod; } for (int i = 63 ; i >= 0 ; --i) { if (v[i] == 0 ) continue ; if (base[i] == 0 ) return false ; ll k = v[i]; for (int j = 0 ; j <= i; ++j) { v[j] = (v[j] - k * mat[i][j]) % mod; if (v[j] < 0 ) v[j] += mod; } } return true ; } }; int main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); int T; cin >> T; while (T--) { modn_XOR_base base (3 ) ; ll N,Q; cin>>N>>Q; for (int i=0 ;i<N;++i){ ll x; cin>>x; base.insert (x); } for (int i=0 ;i<Q;++i){ ll t; cin>>t; cout<<(base.query (t)? "Yes\n" :"No\n" ); } } return 0 ; }
心路历程(WA,TLE,MLE……)