本场题目不难,暴力模拟大法好。A~E:模拟+暴力(有些是贪心);F:留坑待填;G:埃氏筛+贪心。
A、Restoring Three Numbers
思路:简单数学。
AC代码:


1 #include <cstdio>
2 #include <cstring>
3 #include <cstdlib>
4 #include <cmath>
5 #include <iostream>
6 #include <algorithm>
7 #include <iomanip>
8 #include <complex>
9 #include <string>
10 #include <vector>
11 #include <set>
12 #include <map>
13 #include <list>
14 #include <deque>
15 #include <queue>
16 #include <stack>
17 #include <bitset>
18 using namespace std;
19 typedef long long LL;
20 typedef unsigned long long ULL;
21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
24 const double eps = 1e-6;
25 const double PI = acos(-1.0);
26 const int maxn = 1e5+5;
27 const int inf = 0x3f3f3f3f;
28
29
30 LL x[5], a, b, c;
31
32 int main() {
33 while(cin >> x[1] >> x[2] >> x[3] >> x[4]) {
34 sort(x + 1, x + 5);
35 b = (x[1] - x[2] + x[3]) / 2;
36 c = x[3] - b;
37 a = x[4] - b - c;
38 cout << a << ' ' << b << ' ' << c << endl;
39 }
40 return 0;
41 }
B、Make Them Equal
思路:暴力+模拟。只需枚举最终的数组变成的数字(1~100)即可。
AC代码:


1 #include <cstdio>
2 #include <cstring>
3 #include <cstdlib>
4 #include <cmath>
5 #include <iostream>
6 #include <algorithm>
7 #include <iomanip>
8 #include <complex>
9 #include <string>
10 #include <vector>
11 #include <set>
12 #include <map>
13 #include <list>
14 #include <deque>
15 #include <queue>
16 #include <stack>
17 #include <bitset>
18 using namespace std;
19 typedef long long LL;
20 typedef unsigned long long ULL;
21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
24 const double eps = 1e-6;
25 const double PI = acos(-1.0);
26 const int maxn = 105;
27 const int inf = 0x3f3f3f3f;
28
29
30 int n, ans, now, cha, a[maxn];
31 bool flag;
32
33 int main() {
34 while(~scanf("%d", &n)) {
35 for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
36 sort(a, a + n);
37 ans = inf;
38 for(int j = 0; j <= 100; ++j) { // 枚举最终数组中所有的元素变为j
39 now = 0, cha = 0; // 注意:cha的初始值为0,因为1~n每个数都可能与j相同
40 for(int k = 0; k < n; ++k) // 找到第一个与j不同的数求差的绝对值cha
41 if(a[k] != j) {cha = abs(a[k] - j); break;}
42 for(int k = 0; k < n; ++k) { // 模拟即可
43 if(a[k] < j) {
44 if(a[k] + cha == j) ++now;
45 else break;
46 }
47 else if(a[k] > j) {
48 if(a[k] - cha == j) ++now;
49 else break;
50 }
51 else if(a[k] == j) ++now;
52 }
53 if(now == n) ans = min(ans, cha);
54 }
55 if(ans == inf) puts("-1");
56 else printf("%d\n", ans);
57 }
58 return 0;
59 }
C、Gourmet Cat
思路:数学+暴力。由题易得一周内猫吃肉的种类依次为 a、b、c、a、c、b、a。若 $ a \geq 3 \land b \geq 2 \land c \geq 2 $,则先算出轮数;(否则)剩下的枚举每一天作为起点,简单暴力模拟即可。
AC代码:


1 #include <cstdio>
2 #include <cstring>
3 #include <cstdlib>
4 #include <cmath>
5 #include <iostream>
6 #include <algorithm>
7 #include <iomanip>
8 #include <complex>
9 #include <string>
10 #include <vector>
11 #include <set>
12 #include <map>
13 #include <list>
14 #include <deque>
15 #include <queue>
16 #include <stack>
17 #include <bitset>
18 using namespace std;
19 typedef long long LL;
20 typedef unsigned long long ULL;
21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
24 const double eps = 1e-6;
25 const double PI = acos(-1.0);
26 const int maxn = 105;
27 const int inf = 0x3f3f3f3f;
28
29 int a, b, c, d, ans, now1, now2, k, dir0[7] = {0, 1, 2, 0, 2, 1, 0}, cnt[3], cnt1[3];
30
31 int main() {
32 while(cin >> a>> b >> c) {
33 ans = 0;
34 memset(cnt, 0, sizeof(cnt));
35 if(a >= 3 && b >= 2 && c >= 2) {
36 k = min(a / 3, min(b / 2, c / 2));
37 a -= 3 * k, b -= 2 * k, c -= 2 * k;
38 ans = 7 * k;
39 }
40 cnt[0] = a, cnt[1] = b, cnt[2] = c, now2 = 0;
41 for(int i = 0; i < 7; ++i) { // 枚举每一天作为起点
42 cnt1[0] = cnt[0], cnt1[1] = cnt[1], cnt1[2] = cnt[2], now1 = 0;
43 for(int j = i; ; ++j) { // 模拟
44 if(cnt1[dir0[j % 7]] > 0) --cnt1[dir0[j % 7]], ++now1;
45 else break;
46 }
47 now2 = max(now1, now2);
48 }
49 cout << ans + now2 << endl;
50 }
51 return 0;
52 }
D、Walking Robot
思路:简单贪心+模拟。详细思路见代码注释。
AC代码:


1 #include <cstdio>
2 #include <cstring>
3 #include <cstdlib>
4 #include <cmath>
5 #include <iostream>
6 #include <algorithm>
7 #include <iomanip>
8 #include <complex>
9 #include <string>
10 #include <vector>
11 #include <set>
12 #include <map>
13 #include <list>
14 #include <deque>
15 #include <queue>
16 #include <stack>
17 #include <bitset>
18 using namespace std;
19 typedef long long LL;
20 typedef unsigned long long ULL;
21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
24 const double eps = 1e-6;
25 const double PI = acos(-1.0);
26 const int maxn = 2e5+5;
27 const int inf = 0x3f3f3f3f;
28
29 int n, b, a, x, y, ans, s[maxn];
30
31 int main() {
32 while(cin >> n >> x >> y) {
33 ans = 0; b = x, a = y;
34 for(int i = 0; i < n; ++i) cin >> s[i];
35 for(int i = 0; i < n; ++i) {
36 if(s[i]) { // 若被光照
37 if(b) { // 先考虑1个b转换成1个a
38 if(a + 1 <= y) --b, ++a, ++ans; // 最大不超过y
39 else if(a) --a, ++ans; // 不能转,则先减去a
40 else if(b) --b, ++ans; // a为0不能继续减,才看b是否剩余
41 else break;
42 }
43 else if(a) --a, ++ans; // 没有b,则只能减去a
44 else break; // 没法减则退出
45 }else { // 没有被光照,不能转
46 if(a) --a, ++ans; // 先考虑a
47 else if(b) --b, ++ans; // a不能减,再考虑b,因为b的作用遇到光时能产生一个a
48 else break; // 没法减则退出
49 }
50 }
51 cout << ans << endl;
52 }
53 return 0;
54 }
E、Two Teams
思路:题意很简单:每次找当前队列中技能最大的学生,向左向右分别连续选择k个学生作为自己的队员。①暴力险过。②换种思路:用大根堆维护当前序列的最大值,同时标记每个元素分别向前、向后走的第一个位置,剩下的暴力模拟即可。
AC代码一:暴力解。


1 #include <cstdio>
2 #include <cstring>
3 #include <cstdlib>
4 #include <cmath>
5 #include <iostream>
6 #include <algorithm>
7 #include <iomanip>
8 #include <complex>
9 #include <string>
10 #include <vector>
11 #include <set>
12 #include <map>
13 #include <list>
14 #include <deque>
15 #include <queue>
16 #include <stack>
17 #include <bitset>
18 using namespace std;
19 typedef long long LL;
20 typedef unsigned long long ULL;
21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
24 const double eps = 1e-6;
25 const double PI = acos(-1.0);
26 const int maxn = 2e5+5;
27 const int inf = 0x3f3f3f3f;
28
29 int n, k, a, ans[maxn], siz, now, cnt, pos, mp[maxn], lt, rt;
30 vector<int> vec;
31 set<int> stl;
32 set<int>::iterator it;
33
34 int main() {
35 while(~scanf("%d%d", &n, &k)) {
36 memset(ans, 0, sizeof(ans));
37 memset(mp, 0, sizeof(mp));
38 vec.clear();
39 stl.clear();
40 cnt = 0;
41 for(int i = 0; i < n; ++i) {
42 scanf("%d", &a);
43 vec.push_back(a);
44 mp[a] = i;
45 stl.insert(a);
46 }
47 while((siz = stl.size()) != 0) {
48 it = stl.end();
49 --it;
50 ++cnt;
51 if(cnt & 1) now = 1;
52 else now = 2;
53 pos = find(vec.begin(), vec.end(), *it) - vec.begin();
54 lt = max(0, pos - k), rt = min(siz - 1, pos + k);
55 for(int i = lt; i <= rt; ++i) {
56 ans[mp[vec[i]]] = now;
57 stl.erase(vec[i]);
58 }
59 vec.erase(vec.begin() + lt, vec.begin() + rt + 1);
60 }
61 for(int i = 0; i < n; ++i) printf("%d", ans[i]);
62 puts("");
63 }
64 return 0;
65 }
AC代码二:优化解。


1 #include <cstdio>
2 #include <cstring>
3 #include <cstdlib>
4 #include <cmath>
5 #include <iostream>
6 #include <algorithm>
7 #include <iomanip>
8 #include <complex>
9 #include <string>
10 #include <vector>
11 #include <set>
12 #include <map>
13 #include <list>
14 #include <deque>
15 #include <queue>
16 #include <stack>
17 #include <bitset>
18 using namespace std;
19 typedef long long LL;
20 typedef unsigned long long ULL;
21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
24 const double eps = 1e-6;
25 const double PI = acos(-1.0);
26 const int maxn = 2e5+5;
27 const int inf = 0x3f3f3f3f;
28
29 int n, k, a, now1, now2, flag, p1, p2, num, ans[maxn], nex[maxn], per[maxn];
30
31 priority_queue<pair<int, int> > que;
32 bool vis[maxn];
33
34
35 int main() {
36 while(~scanf("%d%d", &n, &k)) {
37 while(!que.empty()) que.pop();
38 memset(ans, 0, sizeof(ans));
39 memset(per, 0, sizeof(per));
40 memset(nex, 0, sizeof(nex));
41 flag = 1;
42 memset(vis, false, sizeof(vis));
43 for(int i = 1; i <= n; ++i) {
44 scanf("%d", &a);
45 que.push(make_pair(a, i));
46 per[i] = i - 1;
47 nex[i] = i + 1;
48 }
49 while(!que.empty()) {
50 now1 = que.top().first, now2 = que.top().second, que.pop();
51 if(vis[now2]) continue;
52 vis[now2] = true;
53 flag = !flag;
54 p1 = per[now2], p2 = nex[now2], ans[now2] = flag + 1;
55 num = k;
56 while(num > 0 && p1 > 0) vis[p1] = true, ans[p1] = flag + 1, --num, p1 = per[p1];
57 num = k;
58 while(num > 0 && p2 <= n) vis[p2] = true, ans[p2] = flag + 1, --num, p2 = nex[p2];
59 per[p2] = p1, nex[p1] = p2;
60 }
61 for(int i = 1; i <= n; ++i) printf("%d", ans[i]);
62 puts("");
63 }
64 return 0;
65 }
G、Minimum Possible LCM
思路:埃氏筛+贪心。题意就是找出2个数使其最小公倍数最小。题目虽然给的时限是4s,但我们要换种优雅的方式来暴力,即来枚举每一个gcd(求lcm需要先求出2个数的gcd)。借用埃氏筛思想,公约数为gcd的步长增长,不难想到,头2次出现的这2个数的最小公倍数一定为gcd时的最小lcm,那么我们就可以用 $O(nlog^n)$的时间复杂度,大约是 $1.6 \times 10^8 $(1s的极限是$ 1.0 \times 10^8 $)即用1s多就可以过掉此题!
AC代码:


1 #include <cstdio>
2 #include <cstring>
3 #include <cstdlib>
4 #include <cmath>
5 #include <iostream>
6 #include <algorithm>
7 #include <iomanip>
8 #include <complex>
9 #include <string>
10 #include <vector>
11 #include <set>
12 #include <map>
13 #include <list>
14 #include <deque>
15 #include <queue>
16 #include <stack>
17 #include <bitset>
18 using namespace std;
19 typedef long long LL;
20 typedef unsigned long long ULL;
21 const int dir[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // 上右下左
22 const int mx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; // 马可走的八个方向
23 const int my[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
24 const double eps = 1e-6;
25 const double PI = acos(-1.0);
26 const LL maxn = 1e7+5;
27 const LL inf = 1LL << 62;
28
29
30 int n, num, p1, p2, per1, per2, siz;
31 LL ans, now0, now1, now2, a;
32
33 bool vis[maxn];
34
35 vector<int> vec[maxn];
36
37
38 int main() {
39 while(~scanf("%d", &n)) {
40 ans = inf;
41 per1 = per2 = 0;
42 for(LL i = 0LL; i < maxn; ++i) vec[i].clear();
43 memset(vis, false, sizeof(vis));
44 for(int i = 1; i <= n; ++i) {
45 scanf("%lld", &a);
46 vec[a].push_back(i);
47 vis[a] = true; // 标记出现的元素
48 }
49 for(LL i = 1LL; i < maxn; ++i) {
50 num = 0;
51 for(LL j = i; j < maxn && num < 2; j += i) {
52 if(!vis[j]) continue;
53 if(num == 0) { // 第一次出现
54 siz = vec[j].size();
55 if(siz == 1) {
56 ++num;
57 p1 = vec[j][0];
58 now1 = j;
59 }
60 else {
61 num += 2; // 头2个
62 p1 = vec[j][0], p2 = vec[j][1];
63 now1 = j, now2 = j;
64 }
65 }else { // 第二次出现
66 ++num;
67 now2 = j;
68 p2 = vec[j][0];
69 }
70 }
71 if(num == 2) {
72 now0 = now1 / i * now2;
73 if(ans > now0) {
74 ans = now0;
75 per1 = p1, per2 = p2;
76 }
77 }
78 }
79 if(per1 > per2) swap(per1, per2);
80 printf("%d %d\n", per1, per2);
81 }
82 return 0;
83 }
来源:oschina
链接:https://my.oschina.net/u/4336279/blog/3569937