题目大意
题目描述
给定三个整数 a,b,c,每次可以选择执行以下两种操作之一:
-
a←a+b
-
a←a⊕b(⊕ 为按位异或运算)
你可以执行任意次上述操作。请判断最终是否能将 a 变为 c。
输入格式
第一行为测试数据组数 T(1≤T≤103)。
接下来 T 行,每组数据包含三个整数 a,b,c(0≤a,c≤1018,1≤b≤1000)。
保证在一个测试点内 ∑b2≤106。
输出格式
对于每组数据,如果最终能将 a 变为 c,输出 YES,否则输出 NO。
样例数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 输入: 5 1 6 7 7 5 13 8 3 16 7 6 17 2 7 8
输出: YES NO YES YES NO
|
样例解释
-
第一组数据 1 6 7:初始 a=1,执行一次加法操作 1+6=7,即可得到 c=7,输出 YES。
-
第二组数据 7 5 13:无法通过进行 +5 或 ⊕5 操作从 7 得到 13,输出 NO。
-
第三组数据 8 3 16:初始 a=8,执行路线可为:
8⊕311+314⊕313+316,最终得到 c=16,输出 YES。
-
第四组数据 7 6 17:初始 a=7,执行路线可为:
7+613⊕611+617,最终得到 c=17,输出 YES。
-
第五组数据 2 7 8:无法通过操作从 2 得到 8,输出 NO。
思路讲解
2025 ICPC Asia Manila Regional(2025 ICPC 马尼拉)——vp 中通过题目总结(把题目对取模的要求用注释写在末尾)
收到这场比赛的题目 E. Long Distance Examination(远程操作克隆机器人,两人在不同迷宫中,B 尽力复刻 A 的所有操作)的启发,我们决定重新把这道题目给再盘一盘。
其实说白了,这道题目也很简单,虽然说数字可能很大,但是,我们可以只关注在 ≡(modb) 的值,我们以这个为状态,进行记忆化 bfs,自然是非常少的(状态数)。
记忆化 bfs 最重要的就是确定状态**。**
当然,光有一个目前 mod b 的值是不够的,我们还需要再确定一个状态。
注意到,mod b 的值,是和这个 +b 相关的一个状态,这个提示我们,要采用一个和异或 b 相关的这个值,作为这个状态的组成部分。
注意到,异或 b 只能改变后 __lg(b)+1 位。
因此,最后 __lg(b)+1 位,确定了异或 b 操作能够增长(或减小的值)。再加上 mod b 的值,就唯一确定了这个状态。因为起点确定了,增长的值也确定了,那就什么都确定了。(这个是因为异或具有不可重复操作性,操作偶数次等于不操作,操作奇数次等于操作一次)
1 2 3 4 5 6 7
| struct ModB_Low_bit { ll mod_b,low_bit,origin; bool operator<(const ModB_Low_bit &o) const { if (o.mod_b!=mod_b) return mod_b<o.mod_b; return low_bit<o.low_bit; } };
|
AC代码
AC
https://qoj.ac/submission/1787588
源代码
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
|
#include <bits/stdc++.h> #define all(vec) vec.begin(),vec.end() #define pct __builtin_popcountll #define ctz __builtin_ctzll #define SZ(a) ((long long) a.size()) #define FOR(i, a, b) for (int i = (a); i <= (b); ++i) #define ROF(i, a, b) for (int i = (a); i >= (b); --i) #define debug(var) cerr << #var <<":"<<var<<"\n"; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x)
using namespace std;
using ll = long long;using ull = unsigned long long; using DB=double;using LD=long double;
using CD=complex<double>; static constexpr ll MAXN=(ll)1e6+10,INF=(1ll<<61)-1; static constexpr ll mod=(ll)1e9+7; static constexpr double eps=1e-8;const double pi=acos(-1.0);
ll lT; struct Con { ll val; int needXor; }; void Solve(){ ll A,B,C; cin>>A>>B>>C; queue<Con> q; if (A==C) { cout<<"YES\n"; return; } q.push({A,true}); auto check=[&](ll x) { if (x<=C) { if ((C-x)%B==0) { return true; } } return false; }; unordered_set<ll> vis; ll timer=0; while (!q.empty()) { auto [val,needXor]=q.front(); ++timer; if (timer>B*B+1000) { break; } q.pop(); if (needXor==false) { if (check(val+B)) { cout<<"YES\n"; return; } if (vis.contains(val+B)) { continue; } vis.insert(val+B); q.push({val+B,true}); }else { if (check(val+B)) { cout<<"YES\n"; return; } if (vis.contains(val+B)) {
}else { vis.insert(val+B); q.push({val+B,true}); } if (check(val^B)) { cout<<"YES\n"; return; } if (vis.contains(val^B)) { continue; } vis.insert(val^B); q.push({(val^B),false}); }
} cout<<"NO\n"; }
signed main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);
cin>>lT; while(lT--) Solve(); return 0; }
|
AC
https://qoj.ac/submission/2095935
源代码(又重新写了一个这个严格的记忆化 bfs)
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 138 139 140
|
#include <bits/stdc++.h> #define all(vec) vec.begin(),vec.end() #define lson(o) (o<<1) #define rson(o) (o<<1|1) #define SZ(a) ((long long) a.size()) #define debug(var) cerr << #var <<" = ["<<var<<"]"<<"\n"; #define debug1d(a) \ cerr << #a << " = ["; \ for (int i = 0; i < (int)(a).size(); i++) \ cerr << (i ? ", " : "") << a[i]; \ cerr << "]\n"; #define debug2d(a) \ cerr << #a << " = [\n"; \ for (int i = 0; i < (int)(a).size(); i++) \ { \ cerr << " ["; \ for (int j = 0; j < (int)(a[i]).size(); j++) \ cerr << (j ? ", " : "") << a[i][j]; \ cerr << "]\n"; \ } \ cerr << "]\n"; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x)
using namespace std;
using ll = long long; using ull = unsigned long long; using DB = double; using i128 = __int128; using CD = complex<double>;
ll lT,testcase;
struct ModB_Low_bit { ll mod_b,low_bit,origin; bool operator<(const ModB_Low_bit &o) const { if (o.mod_b!=mod_b) return mod_b<o.mod_b; return low_bit<o.low_bit; } }; void Solve() { ll A,B,C; cin >> A >> B >> C; do { queue<ModB_Low_bit> q; const ll mask=(1<<(__lg(B)+1))-1; ll cmodb=C%B; if (A%B==cmodb && A<=C) { cout<<"YES\n"; return; } q.push({A%B,mask&A,A}); set<ModB_Low_bit> memo={{A%B,mask&A,A}}; while (!q.empty()) { ModB_Low_bit t=q.front(); q.pop(); for (int i=1;i<=2;++i) { if (i==1) { ModB_Low_bit to=t; to.origin^=B; to.mod_b=to.origin%B; to.low_bit=mask&to.origin; if (to.origin>C && (to.origin^B)>C) { continue; } if (memo.contains(to)) { continue; } if (to.mod_b==cmodb && to.origin<=C) { cout<<"YES\n"; return; } q.push(to); memo.insert(to); }else if (i==2) { ModB_Low_bit to=t; to.origin+=B; to.mod_b=to.origin%B; to.low_bit=mask&to.origin; if (to.origin>C && (to.origin^B)>C) { continue; } if (memo.contains(to)) { continue; } if (to.mod_b==cmodb && to.origin<=C) { cout<<"YES\n"; return; } q.push(to); memo.insert(to); } } } cout<<"NO\n"; return; }while (false); }
signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); #ifdef LOCAL cout.setf(ios::unitbuf); #endif
cin >> lT; for (testcase=1;testcase<=lT;++testcase) Solve(); return 0; }
|
心路历程(WA,TLE,MLE……)
