Codeforces Round #430 (Div. 2) 【A、B、C、D题】
【感谢牛老板对D题的指点OTZ】
codeforces 842 A. Kirill And The Game【暴力】
给定a的范围[l,r],b的范围[x,y],问是否存在a/b等于k。直接暴力判断即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 typedef long long ll; 8 ll l, r, x, y, k; 9 int main() { 10 bool f; 11 while(~scanf("%lld%lld%lld%lld%lld", &l, &r, &x, &y, &k)) { 12 f = 0; 13 for(ll i = x; i <= y; ++i) { 14 if(i * k >= l && i * k <= r) { 15 f = 1; break; 16 } 17 } 18 if(f) puts("YES"); 19 else puts("NO"); 20 } 21 return 0; 22 }
codeforces 842 B. Gleb And Pizza【几何水题】
已知大圆圆心在原点,半径为r,其中外壳厚度为d,给出n个小圆的位置和半径,问有多少个小圆包含在外壳上。水题。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 typedef long long ll; 8 int r, d, x, y, rr, n; 9 int main() { 10 bool f; 11 while(~scanf("%d%d", &r, &d)) { 12 int cnt = 0; 13 int s1 = (r-d), s2 = r; 14 scanf("%d", &n); 15 while(n--) { 16 scanf("%d%d%d", &x, &y, &rr); 17 double a = sqrt(x*x+y*y); 18 if(s1+rr <= a && a <= s2-rr) 19 cnt++; 20 } 21 printf("%d\n", cnt); 22 } 23 return 0; 24 }
codeforces 842 C. Ilya And The Tree【DFS】
题意:给一棵树,根为1,每个节点有一个值,每个节点的美丽值为该节点到根的路径上所有节点的最大公约数,现在要求每个节点的美丽值。每个节点的求解,可以将任意一个节点的值改变为0或者不做任何改变。
题解:从根DFS,用set存储每个节点到根节点的gcd值,记录路径节点都不做改变的gcd值val,往下一个节点走时,若要将节点值置零,直接向set插入val即可,继续操作。最后答案即为每个节点的set的最后一个值(set默认升序排序的)。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 #include <set> 8 using namespace std; 9 typedef long long ll; 10 const int N = 2e5+5; 11 int n; 12 int a[N]; 13 vector<int>g[N]; 14 set<int>s[N]; 15 set<int>::iterator it; 16 int gcd(int a, int b) {return b?gcd(b, a%b):a;} 17 void dfs(int u, int fa, int val) { 18 for(it = s[fa].begin(); it != s[fa].end(); ++it) s[u].insert(gcd(*it, a[u])); 19 s[u].insert(val); 20 val = gcd(val, a[u]); 21 for(int i = 0; i < g[u].size(); ++i) if(g[u][i] != fa) dfs(g[u][i], u, val); 22 } 23 int main() { 24 int i, j, x, y; 25 while(~scanf("%d", &n)) { 26 for(i = 1; i <= n ;++i) {g[i].clear();s[i].clear();} 27 for(i = 1; i <= n; ++i)scanf("%d", &a[i]); 28 for(i = 1; i <= n-1; ++i) { 29 scanf("%d%d", &x, &y); 30 g[x].push_back(y); g[y].push_back(x); 31 } 32 s[0].insert(0); 33 dfs(1, 0, 0); 34 for(i = 1; i <= n; ++i) 35 printf("%d ", *s[i].rbegin()); 36 puts(""); 37 } 38 return 0; 39 }
未完待续,,,
codeforces 842 D. Vitya and Strange Lesson【trie+贪心】
题意:mex为一个序列中没出现的非负最小值,现在序列有n个数,有m个询问,每个询问给一个数,将序列中每个数与x异或,然后查询序列的mex值。
题解:其实就是相当于求没出现的数与x异或的最小值。将序列没出现的数以二进制形式插入trie树中,树上跑x异或的最小值,贪心地让某位的值与x对应的位的值相同即可。
//yy:一开始字典树大小开小了,结果郁闷了很久。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #define CLR(a,b) memset((a),(b),sizeof((a))) 7 using namespace std; 8 typedef long long ll; 9 const int N = 19; 10 const int M = 3e5+5; 11 int n, m; 12 struct Trie { 13 int next[2]; 14 int v; 15 void init() { 16 v = 0; 17 memset(next, -1, sizeof(next)); 18 } 19 }T[N*M*2]; 20 int le; 21 void inser(int x) { 22 int p = 0; 23 for(int i = N-1; i >= 0; --i) { 24 int t = (x>>i) & 1; 25 if(T[p].next[t] == -1) { 26 T[le].init(); 27 T[p].next[t] = le++; 28 } 29 p = T[p].next[t]; 30 } 31 T[p].v = x; 32 } 33 void query(int x) { 34 int i = 0, p = 0; 35 for(int i = N-1; i >= 0; --i) { 36 int t = (x>>i) & 1; 37 if(T[p].next[t] == -1) p = T[p].next[t^1]; 38 else p = T[p].next[t]; 39 } 40 printf("%d\n", x ^ T[p].v); 41 } 42 bool a[1<<N]; 43 int main() { 44 int i, x, y; 45 while(~scanf("%d%d", &n, &m)) { 46 CLR(a, 0); 47 for(i = 1; i <= n; ++i) {scanf("%d", &x); a[x] = 1;} 48 le = 1; T[0].init(); 49 for(i = 0; i <= (1<<N)-1; ++i) if(!a[i]) inser(i); 50 y = 0; 51 while(m--) { 52 scanf("%d", &x); 53 y ^= x; 54 query(y); 55 } 56 } 57 return 0; 58 }