Codeforces Round #270 solution

A.Design Tutorial: Learn from Math

题意:给你一个大于12小于1e6的数,让你把这个数表示为两个合数之和。

解法:筛素数后枚举一个合数判断另一个是否是合数。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <map>
 5 #include <string>
 6 #include <set>
 7 #include <algorithm>
 8 using namespace std;
 9
10 const int N = 1000010;
11
12 int p[N];
13
14 void init() {
15     for(int i = 2; i * i <= N; i++) {
16         if(p[i] == 0) {
17             for(int j = i * i; j < N; j += i) p[j] = 1;
18         }
19     }
20 }
21
22 int a[N];
23
24 int main() {
25     int n;
26     init();
27     scanf("%d", &n);
28     for(int i = 4; i < n; i++) {
29         if(p[i] && p[n - i]) { printf("%d %d\n", i, n - i); return 0; }
30     }
31
32     return 0;
33 }

B.Design Tutorial: Learn from Life

题意:有一些人在1楼要坐电梯,他们分别要前往不同的楼层,电梯最多只能装k个人,电梯从a层开到b层的时间为|a-b|,中间上下人的时间忽略不计。问最少花费多久可以把所有人都运到他们要去的楼层。

解法:明显我们会按去的楼层的大小序来运送,不妨从小到大。然后未必每次运最多的人最优,样例很厚道的给出了反例。我们设f[x]为把去往楼层前x小的人运送完毕的花费,枚举这次运多少人dp即可。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <map>
 5 #include <string>
 6 #include <set>
 7 #include <algorithm>
 8 using namespace std;
 9
10 const int N = 2010;
11
12 int f[N];
13 int a[N];
14
15 int main() {
16     int n, k;
17     scanf("%d%d", &n, &k);
18     for(int i = 0; i < n; i++) scanf("%d", &a[i]);
19     sort(a, a + n);
20     for(int i = 1; i <= n; i++) f[i] = 1000000000;
21     for(int i = 1; i <= n; i++) {
22         for(int j = 1; j <= k; j++) {
23             if(i >= j) f[i] = min(f[i], f[i - j] + 2 * (a[i - 1] - 1));
24         }
25     }
26     printf("%d\n", f[n]);
27
28     return 0;
29 }

C.Design Tutorial: Make It Nondeterministic

题意:有n个人,他们的名字由两个长度不超过50的字符串构成,每个人可以任选其一来代表自己。现在给出这n个人按照他们选择的名字按字典序从小打到的一个排序,问这个排序是否是可能出现的。

解法:我们从名字字典序最小的那个人开始看,显然是使用字典序小的那个比较好,然后对于后面的在满足他选择的这个名字的字典序大于前面那个人的字典序的情况下选择较小的那个,如果不可能那么这个排序不可能出现。详见代码。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <map>
 5 #include <string>
 6 #include <set>
 7 #include <algorithm>
 8 using namespace std;
 9
10 const int N = 200010;
11 struct name {
12     char s[52];
13     int id;
14 }p[N];
15
16 bool cmp(const name &a, const name &b) {
17     return strcmp(a.s, b.s) < 0;
18 }
19
20 int k[2][N], a[N];
21
22 int main() {
23     int n;
24     scanf("%d", &n);
25     for(int i = 0; i < n; i++) {
26         scanf("%s%s", p[2 * i].s, p[2 * i + 1].s);
27         p[2 * i].id = p[2 * i + 1].id = i + 1;
28     }
29     sort(p, p + 2 * n, cmp);
30     for(int i = 0; i < 2 * n; i++) {
31         if(k[0][p[i].id] == 0) k[0][p[i].id] = i + 1;
32         else k[1][p[i].id] = i + 1;
33     }
34     for(int i = 0; i < n; i++) scanf("%d", &a[i]);
35     int now = 0;
36     int f = 0;
37     for(int i = 0; i < n; i++) {
38         if(k[0][a[i]] > now) now = k[0][a[i]];
39         else if(k[1][a[i]] > now) now = k[1][a[i]];
40         else { f = 1; break; }
41     }
42     if(f == 0) printf("YES\n");
43     else printf("NO\n");
44
45     return 0;
46 }

D.Design Tutorial: Inverse the Problem

题意:现在给你一个n*n的数组d表示一棵带正权的树上任意两点间距离,问这样的树是否存在。

解法:如果我们找到现在这个图上最长的距离,那么这条边的两个端点必然是叶子。设一个端点为x,我们找到一个端点为x的最小的距离,假设满足最小距离的另一个端点为y,然后我们只需要判断是否所有的端点都满足d[x][y] + d[y][i] = d[x][i]。如果满足,我们可以删去x这个点继续判断,否则这棵树不存在。注意要先判断对角线全0和对称。(因为某些原因我写了个set排序导致一直tle。。真是sad。。)

P.S. 思考可以发现我们不排序直接去进行这个判断也是对的,原因大家自己思考下吧,可以考虑下删掉这条边之后剩下的两颗子树实际对于这个判断都是满足的。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <map>
 5 #include <vector>
 6 #include <string>
 7 #include <set>
 8 #include <algorithm>
 9 using namespace std;
10
11 const int N = 2010;
12 const int oo = 1000000000 + 10;
13 int a[N][N];
14 int n;
15
16 inline bool check() {
17     for(int i = 0; i < n; i++) {
18         if(a[i][i] != 0) return false;
19         for(int j = 0; j < n; j++) {
20             if(a[i][j] != a[j][i]) return false;
21             if(i != j && a[i][j] == 0) return false;
22         }
23     }
24     return true;
25 }
26
27 vector< pair<int, int> > s;
28
29 int u[N];
30
31 inline bool gao(int x) {
32     int now = oo, k;
33     for(int i = 0; i < n; i++) {
34         if(i == x || u[i] == 1) continue;
35         if(a[x][i] < now) {
36             k = i;
37             now = a[x][i];
38         }
39     }
40     for(int i = 0; i < n; i++) {
41         if(i == x || u[i] == 1) continue;
42         if(a[x][k] + a[k][i] != a[x][i]) return false;
43     }
44     return true;
45 }
46
47 inline int rd()
48 {
49     char ch = getchar();
50     int data = 0;
51     while (ch < ‘0‘ || ch > ‘9‘)
52         ch = getchar();
53     do
54     {
55         data = data*10 + ch-‘0‘;
56         ch = getchar();
57     } while (ch >= ‘0‘ && ch <= ‘9‘);
58     return data;
59 }
60
61 int main() {
62     scanf("%d", &n);
63     for(int i = 0; i < n; i++) {
64         for(int j = 0; j < n; j++) a[i][j] = rd();
65     }
66     if(!check()) { printf("NO\n"); return 0; }
67     for(int i = 0; i < n; i++) {
68         for(int j = i + 1; j < n; j++) {
69             s.push_back(make_pair(-a[i][j], i * 10000 + j));
70         }
71     }
72     int flag = 0;
73     sort(s.begin(), s.end());
74     for(int i = 0; i < (int)s.size(); i++) {
75         int aa = s[i].second / 10000, bb = s[i].second % 10000;
76         if(u[aa] == 1 || u[bb] == 1) continue;
77         if(gao(aa) == false || gao(bb) == false) { flag = 1; break; }
78         u[aa] = u[bb] = 1;
79     }
80     if(flag) printf("NO\n");
81     else printf("YES\n");
82
83     return 0;
84 }

时间: 2024-10-10 21:04:51

Codeforces Round #270 solution的相关文章

Codeforces Round #270

Codeforces Round #270 题目链接 A:我是筛了下素数.事实上偶数仅仅要输出4和x - 4,奇数输出9和x - 9就可以 B:贪心的策略,把时间排序后.取每k个的位置 C:贪心.每次遇到一个人尽量让他用字典序小的,假设不行就大的,假设还是不行就是矛盾了 D:先推断原来矩阵的对角线.和是否是对称矩阵,求出最小生成树后.dfs n次求出每两点之间的距离.然后你和原来的矩阵相比就能够了 代码: A: #include <cstdio> #include <cstring>

Codeforces Round #270(活用prim算法)

D. Design Tutorial: Inverse the Problem time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output There is an easy way to obtain a new task from an old one called "Inverse the problem": we give

Codeforces Round #270 D C B A

谈论最激烈的莫过于D题了! 看过的两种做法不得不ORZ,特别第二种,简直神一样!!!!! 1th:构造最小生成树. 我们提取所有的边出来按边排序,因为每次我们知道边的权值>0, 之后每次把边加入集合中,不断构造,类似  kruskal算法,构造出边后 再对每个点进行整张图的DFS求距离 复杂度O(N^2lgN):对所有边排序的复杂度. 1 #include<bits/stdc++.h> 2 3 #define N 2222 4 using namespace std; 5 typedef

Codeforces Round #270 D Design Tutorial: Inverse the Problem --MST + DFS

题意:给出一个距离矩阵,问是不是一颗正确的带权树. 解法:先按找距离矩阵建一颗最小生成树,因为给出的距离都是最短的点间距离,然后再对每个点跑dfs得出应该的dis[][],再对比dis和原来的mp是否一致即可. 首先还要判断一些东西.具体看代码吧. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #in

Educational Codeforces Round 57 Solution

A. Find Divisible 签到. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int t, l, r; 5 6 int main() 7 { 8 scanf("%d", &t); 9 while (t--) 10 { 11 scanf("%d%d", &l, &r); 12 printf("%d %d\n", l, l * 2); 13

Educational Codeforces Round 59 Solution

A. Digits Sequence Dividing 签. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 1010 5 char s[N]; int n; 6 7 void solve() 8 { 9 if (n == 2 && s[1] >= s[2]) 10 { 11 puts("NO"); 12 return; 13 } 14 else 15 { 16 puts(

Codeforces Round #270 D. Design Tutorial: Inverse the Problem

D. Design Tutorial: Inverse the Problem 与u最近的边肯定是与u直接相连的边,所以可以根据这个建树,然后就可以求树上两点之间的距离,判断是否全部匹配. 1 #define bug(x) cout<<#x<<" is "<<x<<endl; 2 #define IO std::ios::sync_with_stdio(0); 3 #include <bits/stdc++.h> 4 #def

Codeforces Round #270 A B C

ADesign Tutorial: Learn from Math 素数筛 #include<bits/stdc++.h> using namespace std; const int N = 1e6 + 100; int a[N]={0}; int main(){ int n; cin >> n; a[1] = 1; for(int i = 2; i*i <= n; i++){ if(a[i] == 0){ for(int j = i*i; j <= n; j +=

Codeforces Round #315 (Div. 1)

A. Primes or Palindromes? time limit per test 3 seconds memory limit per test 256 megabytes input standard input output standard output Rikhail Mubinchik believes that the current definition of prime numbers is obsolete as they are too complex and un