• 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
    ");
    28                 continue;
    29             }
    30             iter = se[k].upper_bound(s-x);
    31             if(se[k].empty() || iter==se[k].begin()) {
    32                 printf("%d
    ", 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
    ",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
    ",ans);
    84         }
    85     }
    86     return 0;
    87 }
    Trie
  • 相关阅读:
    JSP简单访问数据库
    解析数据存储MySQL
    学习SSH框架
    JavaWEB中读取配置信息
    Eclipse中将Java项目转换成Web项目的方法
    JavaWEB入门
    万能数据库连接类-Oracle、DB2 、Access 、Sql Server
    小米3 打开开发者选项
    coolpad 5879logcat不能输入日志解决办法
    实用开发之-oracle表回滚到一个指定时间的操作语句
  • 原文地址:https://www.cnblogs.com/GoldenFingers/p/9282276.html
Copyright © 2020-2023  润新知