1 struct rec {
2 int a, b; // 两个变量,其中a>=b
3 int val, cnt; // 未来估价val,当前次数cnt
4 rec() {}
5 rec(int a_, int b_, int val_, int cnt_) {
6 a = a_, b = b_, val = val_, cnt = cnt_;
7 }
8 };
9 int n;
10 const int N = 1000000, mod = 999983;
11 priority_queue<rec> q;
12 pair<int, int> ver[N];
13 int head[N], d[N], nxt[N], tot; // 手动hash
14
15 inline bool operator <(const rec &a, const rec &b) {
16 return a.val + a.cnt > b.val + b.cnt;
17 }
18
19 // 估价函数,把a不断自加直至>=n所需的次数(注意a>=b),显然实际所需次数不会小于这一次数
20 inline int calc(int a, int b) {
21 int val = 0;
22 for (; a < n; a *= 2) val++;
23 return val;
24 }
25
26 inline int gcd(int a, int b) {
27 return b ? gcd(b, a%b) : a;
28 }
29
30 inline bool get_or_update(int a, int b, int cnt) {
31 int hash = (long long)a * b % mod;
32 for (int i = head[hash]; i; i = nxt[i]) {
33 if (ver[i].first == a && ver[i].second == b) {
34 if (d[i] > cnt) {
35 d[i] = cnt;
36 return true;
37 }
38 return false;
39 }
40 }
41 d[++tot] = cnt;
42 ver[tot] = make_pair(a, b);
43 nxt[tot] = head[hash], head[hash] = tot;
44 return true;
45 }
46
47 inline void insert(int a, int b, int cnt) {
48 if (a < b) swap(a, b); // 保证a>=b
49 if (n % gcd(a, b)) return; // 剪枝
50 bool updated = get_or_update(a, b, cnt);
51 if (updated) q.push(rec(a, b, calc(a, b), cnt));
52 }
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/245517.html