Codeforces Round #482 (Div. 2) : Kuro and GCD and XOR and SUM (寻找最大异或值)

题目链接:http://codeforces.com/contest/979/problem/D

参考大神博客:https://www.cnblogs.com/kickit/p/9046953.html

解题心得:

  • 题目给了你很多条件,具体起来就是输入三个数x,k,s,在数列中找到一个数num,要求:1. GCD(x, num)%k == 0; 2. x + num <= s;3. num异或x最大
  • 刚开始一看数据量这么大,条件这么多怎么搞。其实前面两个条件是用来剪枝的。首先可以开很多个set,将每一个数放在他因子的set中,这样在面对第一个条件的时候就可以直接在set[k]里面找目标数。然后我们从set[k]中找最大的num,使得x+num<=s,这里寻找第一个数可以在set中使用二分,然后向前便利记录下异或值的Max,如果遍历过程中num+x<=Max直接跳出,因为两个数的异或值<=两个数的和。
  • 其实在寻找异或值最大的问题其实就是用Trie,这个题也可以用Trie,但是节点太多了,只能动态开辟内存,每次new内存速度太慢了。

按照题意剪枝代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 2e5+100;
 4 set <int> se[maxn];
 5 set <int> :: iterator iter;
 6 
 7 int main() {
 8     int n;
 9     scanf("%d",&n);
10     while(n--) {
11         int ope;
12         scanf("%d",&ope);
13         if(ope == 1) {
14             int num;
15             scanf("%d",&num);
16             int sq = sqrt(1.0*num);
17             for(int i=1;i<=sq;i++) {
18                 if(num%i == 0) {
19                     se[i].insert(num);
20                     se[num/i].insert(num);
21                 }
22             }
23         } else {
24             int x,k,s,ans = -1, Max = -1;
25             scanf("%d%d%d",&x,&k,&s);
26             if(x%k) {
27                 printf("-1\n");
28                 continue;
29             }
30             iter = se[k].upper_bound(s-x);
31             if(se[k].empty() || iter==se[k].begin()) {
32                 printf("%d\n", ans);
33                 continue;
34             }
35             iter--;
36             while(iter!=se[k].begin()) {
37                 if(*iter + x < Max)
38                     break;
39                 int temp = (*iter)^x;
40                 if(temp > Max){
41                     Max = temp;
42                     ans = *iter;
43                 }
44                 iter--;
45             }
46             int temp = (*iter)^x;
47             if(temp > Max)
48                 ans = *iter;
49             printf("%d\n",ans);
50         }
51     }
52     return 0;
53 }
View Code

Trie代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e5+100;
 4 
 5 struct node{
 6     int Min;
 7     node* bit[2];
 8     node() {
 9         bit[0] = bit[1] = nullptr;
10         Min = maxn;
11     }
12 };
13 
14 node* head[maxn];
15 int n;
16 
17 set <int> se[maxn];
18 set <int> ::iterator iter;
19 
20 void init() {
21     scanf("%d",&n);
22     for(int i=1;i<maxn;i++) {
23         for(int j=i;j<maxn;j+=i){
24             se[j].insert(i);
25         }
26     }
27     for(int i=0;i<maxn;i++)
28         head[i] = new node();
29 }
30 
31 void insert_tree(int va, int u) {
32     node *cur = head[va];
33     cur->Min = min(cur->Min, u);
34     for(int i=18;i>=0;i--) {
35         int b = (u>>i)&1;
36         if(cur->bit[b] == nullptr){
37             cur->bit[b] = new node();
38             cur = cur->bit[b];
39             cur->Min = min(cur->Min, u);
40         } else {
41             cur = cur->bit[b];
42             cur->Min = min(cur->Min, u);
43         }
44     }
45 }
46 
47 int query(int x, int k, int s) {
48     if(head[k]->Min > s -x || x%k != 0)
49         return -1;
50     node *cur;
51     cur = head[k];
52     int res = cur->Min;
53     for(int i=18;i>=0;i--){
54         int b = (x>>i)&1;
55         int Xor = b^1;
56         if(cur->bit[Xor] != nullptr && cur->bit[Xor]->Min + x <= s) {
57             res = cur->bit[Xor]->Min;
58             cur = cur->bit[Xor];
59         } else {
60             cur = cur->bit[b];
61             res = cur->Min;
62         }
63     }
64     return res;
65 }
66 
67 int main() {
68     init();
69     while(n--) {
70         int ope;
71         scanf("%d",&ope);
72         if(ope == 1) {
73             int u;
74             scanf("%d",&u);
75             for(iter=se[u].begin();iter!=se[u].end();iter++) {
76                 int temp = *iter;
77                 insert_tree(temp, u);
78             }
79         } else {
80             int x, k, s;
81             scanf("%d%d%d",&x,&k,&s);
82             int ans = query(x, k, s);
83             printf("%d\n",ans);
84         }
85     }
86     return 0;
87 }
Trie

猜你喜欢

转载自www.cnblogs.com/GoldenFingers/p/9282276.html