安徽大学第九届程序设计竞赛决赛题解

A.调酒师

很水的一道题,算出每个参数的最小值就行,手速选手被碾压的开始QAQ。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main() {
 5     //freopen("in.txt", "r", stdin);
 6     int T;
 7     int n, a, b, c, d, e, f, g;
 8     cin >> T;
 9     while (T--) {
10         cin >> n;
11         cin >> a >> b >> c >> d >> e >> f >> g;
12         int A = a * b;
13         int B = c * d;
14         int a1, a2, a3;
15         a1 = A / f; a2 = B; a3 = e / g;
16         int ans = min(a1, min(a2, a3));
17         cout << ans / n << endl;
18     }
19 
20     return 0;
21 }
View Code

B.下一个幸运数

本场比赛难度第三的题目,一开始当成数位DP做,一个半小时debug无果,最后发现幸运数总共就1000多个,存起来暴力扫描相加就行 。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 vector<ll> vec;
 5 vector<ll>::iterator it;
 6 set<ll> ss;
 7 char s[15];
 8 
 9 void dfs(int cur, bool zero, ll sum) {
10     if (cur == 11) return;
11     if (!ss.count(sum)) {
12         ss.insert(sum);
13         vec.push_back(sum);
14     }
15     if (zero) {
16         dfs(cur+1, 1, 0);
17         dfs(cur+1, 0, 4);
18         dfs(cur+1, 0, 7);
19     }
20     else {
21         dfs(cur+1, 0, sum*10+4);
22         dfs(cur+1, 0, sum*10+7);
23     }
24 }
25 
26 int main() {
27     dfs(0, 1, 0);
28     sort(vec.begin(), vec.end());
29     it = vec.begin();
30     int T;
31     cin >> T;
32     while (T--) {
33         ll l, r;
34         cin >> l >> r;
35         int cnt = 0, len = vec.size();
36         for (int i = 0; i < len; ++i, ++cnt) if (l <= vec[i]) break;
37         int xx = min(vec[cnt], r) - l + 1;
38         ll ans = xx * vec[cnt];
39         //cout << xx << endl;
40         ll temp = vec[cnt];
41         int cnt2 = cnt + 1;
42         for (int i = cnt + 1; i < len; ++i, ++cnt2) {
43             if (vec[i] > r) break;
44             int yy = vec[i] - temp;
45             temp = vec[i];
46             ans += yy * vec[i];
47         }
48         if (vec[cnt2-1] < r) {
49             int zz = r-vec[cnt2-1];
50             ans += zz * vec[cnt2];
51         }
52         cout << ans << endl;
53     }
54 
55     return 0;
56 }
View Code

C.最短路径和

做出这道题目需要灵活掌握Floyd的原理,比赛时只会个形式便没写出来。实际上只需要记录删点的次序,倒叙用来当中转点更新路径,统计ans的时候只统计目前存在的点。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define M(a, b) memset(a, b, sizeof(a))
 4 #define INF 0x3f3f3f3f
 5 typedef long long ll;
 6 const int N = 400 + 5;
 7 int G[N][N], d[N][N], n, q[N], ans[N];
 8 
 9 void Floyd() {
10     M(ans, 0);
11     for (int kk = n; kk >= 1; --kk) {
12         int k = q[kk];
13         for (int i = 1; i <= n; ++i)
14             for (int j = 1; j <= n; ++j) {
15                 d[i][j] = min(d[i][j], d[i][k]+d[k][j]);
16             }
17         for (int i = kk; i <= n; ++i)
18             for (int j = kk; j <= n; ++j)
19                 ans[kk] += d[q[i]][q[j]];
20     }
21     cout << ans[1];
22     for (int i = 2; i <= n; ++i) cout << " " << ans[i];
23     cout << endl;
24 }
25 
26 int main() {
27     ios::sync_with_stdio(false);
28     while (cin >> n) {
29         M(G, 0); M(d, INF);
30         for (int i = 1; i <= n; ++i)
31             for (int j = 1; j <= n; ++j)
32                 cin >> d[i][j];
33         for (int i = 1; i <= n; ++i) cin >> q[i];
34         Floyd();
35     }
36 
37     return 0;
38 }
View Code

D. 西瓜的编译原理作业

贼裸的字典树,不需要任何技巧,不会字典树拿指针模拟都可以做。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define INF 0x3f3f3f3f
 4 #define M(a, b) memset(a, b, sizeof(a))
 5 #define idx(a) a - 'A'
 6 const int maxn = 5000 + 10;
 7 int ch[maxn*70][27], val[maxn*70], tot;
 8 char s[100];
 9 
10 void Insert(char *s) {
11     int now = 0, len = strlen(s), id;
12     for (int i = 0; i < len; ++i) {
13         id = idx(s[i]);
14         if (!ch[now][id]) ch[now][id] = ++tot;
15         now = ch[now][id];
16     }
17     val[now] = 1;
18 }
19 
20 int ans = 0;
21 void dfs(int now) {
22     ans++;
23     for (int i = 0; i < 26; ++i)
24         if (ch[now][i]) dfs(ch[now][i]);
25 }
26 
27 int main() {
28     //freopen("D://in.txt", "r", stdin);
29     while (cin >> s) {
30         Insert(s);
31     }
32     dfs(0);
33     cout << ans << endl;
34 
35     return 0;
36 }
View Code

E. 晋级下一轮

排序

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[200];
 4 
 5 bool cmp(int a, int b) {return a > b;}
 6 
 7 int main() {
 8     //freopen("D://in.txt", "r", stdin);
 9     int T;
10     int n, k;
11     cin >> T;
12     while (T--) {
13         cin >> n >> k;
14         for (int i = 0; i < n; ++i) cin >> a[i];
15         sort(a, a+n, cmp);
16         int cnt = 1;
17         int temp = a[0], kk;
18         int i;
19         bool flag = 0;
20         kk = a[k-1];
21         //cout << kk << endl;
22         int ans = 0;
23         for (int i = 0; i < n; ++i) if (a[i] >= kk && a[i]) ++ans;
24         cout << ans << endl;
25     }
26 
27     return 0;
28 }
View Code

F. 西瓜和病毒

把特征串建立成AC自动机,再从root开始跑,如果存在一个环(环的路径上不包括任何特征串,也就是不经过val值为1的点),就存在一个安全串,这题的一个trick就是如果某个点u的失配指针f[u]的val为1,要把val[u]也赋值为1,因为root~f[u]为root~u的后缀。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define idx(a) a - '0'
 4 #define M(a, b) memset(a, b, sizeof(a))
 5 #define INF 0x3f3f3f3f
 6 const int N = 30000 + 5;
 7 char s[N];
 8 
 9 struct ac_mata {
10     int ch[N][2], f[N], in[N], val[N], tot;
11     bool vis[N];
12 
13     void init() {
14         tot = 0;
15         M(f, 0); M(in, 0); M(vis, 0); M(val, 0); M(ch, 0);
16     }
17 
18     void insert(char *s) {
19         int now = 0, id, len = strlen(s);
20         for (int i = 0; i < len; ++i) {
21             id = idx(s[i]);
22             if (!ch[now][id]) ch[now][id] = ++tot;
23             now = ch[now][id];
24         }
25         val[now] = 1;
26     }
27 
28     void getFail() {
29         queue<int> q;
30         int u;
31         for (int i = 0; i < 2; ++i) {
32             u = ch[0][i];
33             if (u) {f[u] = 0; q.push(u);}
34         }
35         while (!q.empty()) {
36             u = q.front(); q.pop();
37             for (int i = 0; i < 2; ++i) {
38                 int v = ch[u][i];
39                 if (!v) {ch[u][i] = ch[f[u]][i]; continue;}
40                 q.push(v);
41                 int k = f[u];
42                 if (k && !ch[k][i]) k = f[k];
43                 f[v] = ch[k][i];
44                 val[v] |= val[f[v]];
45             }
46         }
47     }
48 
49     bool findcircle(int x) {
50         in[x] = 1;
51         for (int i = 0; i < 2; ++i) {
52             int u = ch[x][i];
53             if (in[u]) return 1;
54             if (vis[u] || val[u]) continue;
55             vis[u] = 1;
56             if (findcircle(u)) return 1;
57         }
58         in[x] = 0;
59         return 0;
60     }
61 
62 }ac;
63 
64 int main() {
65     ios::sync_with_stdio(false);
66     int n;
67     while (cin >> n) {
68         ac.init();
69         while (n--) {
70             cin >> s;
71             ac.insert(s);
72         }
73         ac.getFail();
74         if (ac.findcircle(0)) cout << "TAK" << endl;
75         else cout << "NIE" << endl;
76     }
77 
78     return 0;
79 }
View Code

G. 黑白棋

大水题,题面把行写成了列,debug很久,头皮发麻。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char s[20];
 4 char a[12][12];
 5 bool b[13];
 6 vector<int> vec;
 7 
 8 int main() {
 9     //freopen("D://in.txt", "r", stdin);
10     int n;
11     cin >> n;
12     while (n--) {
13         memset(b, 0, sizeof(b));
14         vec.clear();
15         int ans = 0;
16         scanf("%s", s+1);
17         bool flag = 0;
18         for (int j = 1; j <= 12; j++) {
19             if (12 % j) continue;
20             for (int i = 1; i <= j; ++i) {
21                 flag = 1;
22                 for (int k = i; k <= 12; k += j)
23                     if (s[k] == 'O') flag = 0;
24                 if (flag) break;
25             }
26             if (flag) vec.push_back(j), ++ans;
27         }
28         cout << ans;
29         for (int i = vec.size()-1; i >= 0; --i) {
30             int c = vec[i];
31             cout << " " << 12 / c << "x" << c;
32         }
33         cout << endl;
34     }
35 
36     return 0;
37 }
View Code

H. 勤劳的出题人

两个指针指向两个数组,一一比较,最后总数减去成功匹配的数量即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 3000 + 10;
 4 int a[maxn], b[maxn];
 5 bool vis[maxn], have[1000010];
 6 
 7 int main() {
 8     //freopen("D://in.txt", "r", stdin);
 9     int n, m;
10     while (cin >> n >> m) {
11         memset(have, 0, sizeof(have));
12         memset(vis, 0, sizeof(vis));
13         for (int i = 1; i <= n; ++i) cin >> a[i];
14         for (int j = 1; j <= m; ++j) {
15                 cin >> b[j];
16         }
17         sort(a+1, a+n+1);
18         sort(b+1, b+m+1);
19         int cnt = 0;
20         int i = 1, j = 1;
21         while (i <= n && j <= m){
22             if (a[i] <= b[j]) {
23                 ++i;
24                 ++j;
25                 ++cnt;
26             }
27             else ++j;
28         }
29         cout << n - cnt << endl;
30     }
31 
32     return 0;
33 }
View Code
原文地址:https://www.cnblogs.com/robin1998/p/6629372.html