手写堆(优先队列),手写hash


 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/245517.html

(0)
上一篇 2022年4月18日
下一篇 2022年4月18日

相关推荐

发表回复

登录后才能评论