A:略坑 枚举l-r,看是否能整除k且商的范围是不是在x,y里
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; int l, r, x, y, k; int main() { cin >> l >> r >> x >> y >> k; for(int i = l; i <= r; ++i) if(i % k == 0) { int t = i / k; if(t >= x &&t <=y ) { puts("YES"); return 0; } } puts("NO"); return 0; }
B:判断一下就行了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; double r, d; int n, ans; double dis(double x, double y) { return sqrt(x * x + y * y); } int main() { cin >> r >> d >> n; for(int i = 1; i <= n; ++i) { double x, y, R; scanf("%lf%lf%lf", &x, &y, &R); double dist = dis(x, y); if(dist - R >= r - d && dist + R <= r) ++ ans; } printf("%d ", ans); return 0; }
C:和一道poi的题有同样的性质,可是那道题我忘了。。。
其实我们发现,每次如果一个数和另一个数的gcd,要么不变,要么至少除以2,所以我们每个节点开个set,保存把一个节点赋0的所有gcd和没有赋过0的gcd,这样其实每个节点能够得到的gcd只有log个,然后我们暴力把自己父亲节点的gcd和这个节点的数做一个gcd,相当于这个节点的值取0,然后一直dfs,最后输出每个节点的set里的最大值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<set> #include<vector> #include<iostream> using namespace std; const int N = 200010; struct edge { int nxt, to; } e[N << 1]; int n, cnt = 1; int head[N], a[N]; set<int> s[N]; void link(int u, int v) { e[++cnt].nxt = head[u]; head[u] = cnt; e[cnt].to = v; } void dfs(int u, int last, int g) { s[u].insert(g); // 这个点为0 // s[u].insert(__gcd(g, a[u])); for(set<int> :: iterator it = s[last].begin(); it != s[last].end(); ++it) s[u].insert(__gcd(a[u], *it)); for(int i = head[u]; i; i = e[i].nxt) if(e[i].to != last) dfs(e[i].to, u, __gcd(g, a[u])); } int main() { scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); for(int i = 1; i < n; ++i) { int u, v; scanf("%d%d", &u, &v); link(u, v); link(v, u); } s[0].insert(0); dfs(1, 0, 0); for(int i = 1; i <= n; ++i) printf("%d ", *(s[i].rbegin())); return 0; }
D:比赛时没用trie树各种调不出来。。。看来我对trie树的理解不够深刻。。。
我们可以想到,我们把每个数插入trie树,然后我们维护每个节点的子树是否满了,然后贪心,如果这位为0的子树没满,那么自然向为0的子树走,否则只能向为1的子树走,每次异或一个数我们就在trie树上打标记,像普通splay一样就行了 注意每次要把标记传给两个儿子,不仅仅是交换两个儿子
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; const int N = 300010; int n, m, last, cnt = 1; int vis[N]; struct Trie { struct node { int full, ch[2], rev; } t[N * 10]; void pushdown(int x, int bit) { if(!t[x].rev) return; t[t[x].ch[0]].rev ^= t[x].rev; t[t[x].ch[1]].rev ^= t[x].rev; if(t[x].rev & (1 << bit)) swap(t[x].ch[0], t[x].ch[1]); t[x].rev = 0; } void insert(int x, int num, int bit) { if(bit == -1) { t[x].full = 1; return; } int b = (num & (1 << bit)) > 0; if(t[x].ch[b] == 0) t[x].ch[b] = ++cnt; insert(t[x].ch[b], num, bit - 1); t[x].full = t[t[x].ch[0]].full & t[t[x].ch[1]].full; } int query(int x, int num, int bit) { if(bit == -1) return 0; pushdown(x, bit); if(t[t[x].ch[0]].full) return query(t[x].ch[1], num, bit - 1) + (1 << bit); else return query(t[x].ch[0], num, bit - 1); } } trie; int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; ++i) { int x; scanf("%d", &x); if(vis[x] == 0) { vis[x] = 1; trie.insert(1, x, 20); } } while(m --) { int x; scanf("%d", &x); trie.t[1].rev ^= x; printf("%d ", trie.query(1, last, 20)); } return 0; }
这次cf的题目挺不错的,但是由于自己傻逼trie树写不对滚粗了。。。