codeforces 979D Kuro and GCD and XOR and SUM

题意:

给出两种操作:

1.添加一个数字x到数组。

2.给出s,x,k,从数组中找出一个数v满足gcd(x,k) % v == 0 && x + v <= s && (x xor v 最大),如果没有,输出-1.

思路:

有两种做法。

第一种,首先用若干个set存因子中有k的数字。

然后每次在set[k]中二分找到大于s-x的第一个数,然后从大到小开始找,假设sum为当前x xor v的最大值,那么当当前的*it +x < sum,那么就直接break,原理是因为a ^ b <= a + b。

这个没有优化之前是会tle,但是加了优化之后比字典树跑得快了许多。。。

第二种,对于每一个数,都把它添加到它的因子的01字典树当中去,然后根据x xor v最大这个经典问题,找 xor 最大,字典树是个好东西。

代码1;

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <set>
 5 #include <math.h>
 6 using namespace std;
 7 const int N = 1e5 + 11;
 8 set<int> mmp[N];
 9 int main()
10 {
11     int n;
12     scanf("%d",&n);
13     while (n--)
14     {
15         int t;
16         scanf("%d",&t);
17         if (t == 1)
18         {
19             int u;
20             scanf("%d",&u);
21             int m = sqrt(1.0 * u);
22             for (int i = 1;i <= m;i++)
23             {
24                 if (u % i == 0)
25                 {
26                     mmp[i].insert(u);
27                     mmp[u/i].insert(u);
28                 } 
29             }
30         }
31         else
32         {
33             int x,k,s;
34             scanf("%d%d%d",&x,&k,&s);
35             int sum = -1;
36             int ans = -1;
37             if (x % k)
38             {
39                 printf("%d\n",ans);
40                 continue;
41             }
42             auto it = mmp[k].upper_bound(s-x);
43             if (mmp[k].empty() || it == mmp[k].begin())
44             {
45                 printf("%d\n",ans);
46                 continue;
47             }
48             --it;
49             for (;it != mmp[k].begin();--it)
50             {
51                 if (sum > x + *it) break;
52                 if (sum < (x ^ *it))
53                 {
54                     ans = *it;
55                     sum = x ^ *it;
56                 }
57             }
58             if (sum < (x ^ *it))
59             {
60                 ans = *it;
61                 sum = x ^ *it;
62             }
63             printf("%d\n",ans);
64         }
65     }
66     return 0;
67 }

代码2:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <stdlib.h>
 5 #include <set>
 6 using namespace std;
 7 const int N = 1e5 + 10;
 8 set<int> g[N];
 9 struct node
10 {
11     int mi;
12     struct node* bit[2];
13     node()
14     {
15         mi = N;
16         bit[0] = bit[1] = nullptr;
17     }
18 };
19 node *a[N];
20 void update(int x,int u)
21 {
22     node* cu = a[x];
23     cu -> mi = min(cu -> mi,u);
24     for (int i = 18;i >= 0;i--)
25     {
26         int b = u >> i & 1;
27         if (cu -> bit[b] != nullptr)
28         {
29             cu = cu -> bit[b];
30             cu -> mi = min(cu -> mi,u);
31         }
32         else
33         {
34             cu -> bit[b] = new node();
35             cu = cu -> bit[b];
36             cu -> mi = min(cu -> mi,u);
37         }
38     }
39 }
40 int que(int x,int k,int s)
41 {
42     node *cu = a[k];
43     if (x % k || cu -> mi > s - x) return -1;
44     int ret = cu -> mi;
45     for (int i = 18;i >= 0;i--)
46     {
47         int b = x >> i & 1;
48         if (cu -> bit[b^1] != nullptr && cu -> bit[b^1] -> mi + x <= s)
49         {
50             cu = cu -> bit[b^1];
51             ret = cu -> mi;
52         }
53         else
54         {
55             cu = cu -> bit[b];
56             ret = cu -> mi;
57         }
58     }
59     return ret;
60 }
61 int main()
62 {
63     int q;
64     for (int i = 1;i < N;i++)
65     {
66         for (int j = i;j < N;j += i)
67         {
68             g[j].insert(i);
69         }
70     }
71     for (int i = 1;i < N;i++) a[i] = new node();
72     scanf("%d",&q);
73     while (q--)
74     {
75         int t;
76         scanf("%d",&t);
77         if (t==1)
78         {
79             int u;
80             scanf("%d",&u);
81             for (auto x : g[u])
82             {
83                 update(x,u);
84             }
85         }
86         else
87         {
88             int x,s,k;
89             scanf("%d%d%d",&x,&k,&s);
90             int ans = que(x,k,s);
91             printf("%d\n",ans);
92         }
93     }
94     return 0;
95 }

 

posted @ 2018-05-16 17:12  qrfkickit  阅读(532)  评论(0编辑  收藏  举报