
ProblemA(Codeforces Round 689A):
题意:
给一个手势, 问这个手势是否是唯一。
思路:
暴力, 模拟将这个手势上下左右移动一次看是否还在键盘上即可。
代码:
1 #include <cmath>
2 #include <cstdio>
3 #include <cstring>
4 #include <cstdlib>
5 #include <ctime>
6 #include <set>
7 #include <map>
8 #include <list>
9 #include <stack>
10 #include <queue>
11 #include <string>
12 #include <vector>
13 #include <fstream>
14 #include <iterator>
15 #include <iostream>
16 #include <algorithm>
17 using namespace std;
18 #define LL long long
19 #define INF 0x3f3f3f3f
20 #define MOD 1000000007
21 #define eps 1e-6
22 #define MAXN 10
23 #define MAXM 100
24 #define dd {cout<<"debug"<<endl;}
25 #define pa {system("pause");}
26 #define p(x) {printf("%d\n", x);}
27 #define pd(x) {printf("%.7lf\n", x);}
28 #define k(x) {printf("Case %d: ", ++x);}
29 #define s(x) {scanf("%d", &x);}
30 #define sd(x) {scanf("%lf", &x);}
31 #define mes(x, d) {memset(x, d, sizeof(x));}
32 #define do(i, x) for(i = 0; i < x; i ++)
33 #define dod(i, x, l) for(i = x; i >= l; i --)
34 #define doe(i, x) for(i = 1; i <= x; i ++)
35 int n;
36 int row[MAXN] = {4, 1, 1, 1, 2, 2, 2, 3, 3, 3};
37 int col[MAXN] = {2, 1, 2, 3, 1, 2, 3, 1, 2, 3};
38 int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
39 char str[MAXN];
40
41 bool move_one_step(int d)
42 {
43 for(int i = 0; i < n; i ++)
44 {
45 int x = str[i] - '0';
46 if((d == 2 || d == 3) && x == 0) return false;
47 if(row[x] + dir[d][0] < 1 || col[x] + dir[d][1] < 1 || col[x] + dir[d][1] > 3)
48 return false;
49 if(x != 8 && (row[x] + dir[d][0] > 3))
50 return false;
51 }
52 return true;
53 }
54
55 void get_ans()
56 {
57 bool flag = false;
58 for(int d = 0; d < 4; d ++)
59 {
60 if(move_one_step(d)) flag = true;
61 }
62 printf(flag ? "NO\n" : "YES\n");
63 }
64
65 int main()
66 {
67 scanf("%d", &n);
68 scanf("%s", str);
69
70 get_ans();
71 return 0;
72 }Problem_B(Codeforces Round 689B):
题意:
有n个城市, 第i个城市到第j个城市需要消耗abs(i - j)的能量, 然后每个城市可以转移到另一个城市, 只需要一个能量, 转移是单向的。
问从第一个城市到各个城市所需要的最少能量。
思路:
每次只有三个选择, 即(1、向左走一步, 2、向右走一步, 3、移动到另一个城市)。
以第一个城市为起点, bfs一遍, 即可得到从第一个城市到所有城市所需要的最少能量。
代码:
1 #include <cmath>
2 #include <cstdio>
3 #include <cstring>
4 #include <cstdlib>
5 #include <ctime>
6 #include <set>
7 #include <map>
8 #include <list>
9 #include <stack>
10 #include <queue>
11 #include <string>
12 #include <vector>
13 #include <fstream>
14 #include <iterator>
15 #include <iostream>
16 #include <algorithm>
17 using namespace std;
18 #define LL long long
19 #define INF 0x3f3f3f3f
20 #define MOD 1000000007
21 #define eps 1e-6
22 #define MAXN 200010
23 #define MAXM 100
24 #define dd {cout<<"debug"<<endl;}
25 #define pa {system("pause");}
26 #define p(x) {printf("%d\n", x);}
27 #define pd(x) {printf("%.7lf\n", x);}
28 #define k(x) {printf("Case %d: ", ++x);}
29 #define s(x) {scanf("%d", &x);}
30 #define sd(x) {scanf("%lf", &x);}
31 #define mes(x, d) {memset(x, d, sizeof(x));}
32 #define do(i, x) for(i = 0; i < x; i ++)
33 #define dod(i, x, l) for(i = x; i >= l; i --)
34 #define doe(i, x) for(i = 1; i <= x; i ++)
35 int n;
36 int a[MAXN];
37 int step[MAXN];
38 bool vis[MAXN];
39
40 void update(int pos)
41 {
42 for(int i = pos + 1; i <= n; i ++)
43 step[i] = min(step[i], step[pos] + (i - pos));
44 for(int i = 1; i < pos; i ++)
45 step[i] = min(step[i], step[pos] + pos - i);
46 }
47
48 void show()
49 {
50 for (int i = 1; i <= n; i ++)
51 printf("%d ", step[i]);
52 printf("\n");
53 }
54
55 void bfs()
56 {
57 queue <int> Q;
58 Q.push(1);
59 step[1] = 0;
60 while (!Q.empty())
61 {
62 int cnt = Q.front();
63 Q.pop();
64
65 if(vis[cnt]) continue;
66
67 vis[cnt] = true;
68
69 //left
70 if(step[cnt - 1] > step[cnt] + 1 && cnt - 1 > 0)
71 {
72 step[cnt - 1] = step[cnt] + 1;
73 if(!vis[cnt - 1])
74 Q.push(cnt - 1);
75 }
76
77 //right
78 if(step[cnt + 1] > step[cnt] + 1 && cnt + 1 <= n)
79 {
80 step[cnt + 1] = step[cnt] + 1;
81 if(!vis[cnt + 1])
82 Q.push(cnt + 1);
83 }
84
85 //move
86 if(a[cnt] != cnt)
87 {
88 if(step[a[cnt]] > step[cnt] + 1)
89 {
90 step[a[cnt]] = step[cnt] + 1;
91 if(!vis[a[cnt]])
92 Q.push(a[cnt]);
93 }
94 }
95 }
96 }
97
98 int main()
99 {
100 scanf("%d", &n);
101 mes(vis, false);
102 mes(step, 0x3f);
103 for (int i = 1; i <= n; i ++)
104 {
105 scanf("%d", &a[i]);
106 // step[i] = i - 1;
107 }
108
109 bfs();
110 show();
111 return 0;
112 }Problen_C(Codeforces Round 689C):
题意:
有四个小偷, 假设第一个小偷偷了a块巧克力, 那么第二个小偷则偷了a*k块, 第三个a*k*k块,第四个a*k*k*k个。
然而所有小偷的背包都有一个容量n, 现在给你一个m, 表示小偷们恰好有m种可能偷法。
求满足上述条件的n, n为恰好满足上述条件的最大的背包容量n, 要使得n尽可能的小。
思路:
最值最大/小化, 典型的二分。
由于a, k, n 都是未知的, 先来看一下它们的关系:
第四个小偷偷到a*k^3块巧克力, 是四个小偷里偷到的最多的。
假设现在已知n, 那么如果n/(x^3) > 0, 说明这个x是一个满足条件的k。
然后再看a, a = n / (x^3), 那么从1 ~ a 条件n/(x^3)都是成立的。
所以, 当k = x时, 有n/(x^3)种方案。
那么, 可以知道, 如果n已知, 则可以求出其方案数。
这里就可以二分n, 找到一个满足的n, 然后在这个范围内去找到最小的n.
代码:
1 #include <cmath>
2 #include <cstdio>
3 #include <cstring>
4 #include <cstdlib>
5 #include <ctime>
6 #include <set>
7 #include <map>
8 #include <list>
9 #include <stack>
10 #include <queue>
11 #include <string>
12 #include <vector>
13 #include <fstream>
14 #include <iterator>
15 #include <iostream>
16 #include <algorithm>
17 using namespace std;
18 #define LL long long
19 #define INF 0x7ffffffffffffff
20 #define MOD 1000000007
21 #define eps 1e-6
22 #define MAXN 1000010
23 #define MAXM 100
24 #define dd {cout<<"debug"<<endl;}
25 #define pa {system("pause");}
26 #define p(x) {printf("%d\n", x);}
27 #define pd(x) {printf("%.7lf\n", x);}
28 #define k(x) {printf("Case %d: ", ++x);}
29 #define s(x) {scanf("%d", &x);}
30 #define sd(x) {scanf("%lf", &x);}
31 #define mes(x, d) {memset(x, d, sizeof(x));}
32 #define do(i, x) for(i = 0; i < x; i ++)
33 #define dod(i, x, l) for(i = x; i >= l; i --)
34 #define doe(i, x) for(i = 1; i <= x; i ++)
35 LL m;
36
37 LL check(LL n)
38 {
39 LL sum = 0;
40 for (LL i = 2; ; i ++)
41 {
42 if (n < i * i * i) return sum;
43
44 sum = sum + n / (i * i * i);
45 }
46 return sum;
47 }
48
49 LL get_ans(LL &mid)
50 {
51 LL l = 1, r = INF;
52 LL num = 0;
53
54 while (l < r)
55 {
56 mid = (l + r + 1) / 2;
57 num = check(mid);
58 if (num == m) return num;
59 if (num > m) r = mid - 1;
60 else l = mid + 1;
61 }
62 return num == m ? num : -1;
63 }
64
65 int main()
66 {
67 scanf("%lld", &m);
68 LL n = 0, mid;
69 LL m1 = get_ans(mid);
70 if(m1 != m) printf("-1\n");
71 else
72 {
73 for(LL i = 2; ; i ++)
74 {
75 if(i * i * i > mid) break;
76 n = max(n, mid / (i * i * i) * (i * i * i));
77 }
78 printf("%lld\n", n);
79 }
80 return 0;
81 }Problem_D(CodeForces 689D):
题意:
有两个长度为n的数列a, b。
找出下列子序列的个数:
在[l, r]这个区间内, a数列的最大值 == b数列的最小值。
思路:
求最大最小值, 可以用RMQ, 线段树。
又不涉及修改, 可以使用RMQ, 查询为O(1), 预处理复杂度为O(nlogn)
先将a, b 数列进行处理。
然后, 枚举左端点, 然后再找到满足条件的 右端点的范围, 计算求和即可。
代码:
1 #include <cmath>
2 #include <cstdio>
3 #include <cstring>
4 #include <cstdlib>
5 #include <ctime>
6 #include <set>
7 #include <map>
8 #include <list>
9 #include <stack>
10 #include <queue>
11 #include <string>
12 #include <vector>
13 #include <fstream>
14 #include <iterator>
15 #include <iostream>
16 #include <algorithm>
17 using namespace std;
18 #define LL long long
19 #define INF 0x3f3f3f3f
20 #define MOD 1000000007
21 #define eps 1e-6
22 #define MAXN 200010
23 #define MAXM 21
24 #define dd {cout<<"debug"<<endl;}
25 #define pa {system("pause");}
26 #define p(x) {printf("%d\n", x);}
27 #define pd(x) {printf("%.7lf\n", x);}
28 #define k(x) {printf("Case %d: ", ++x);}
29 #define s(x) {scanf("%d", &x);}
30 #define sd(x) {scanf("%lf", &x);}
31 #define mes(x, d) {memset(x, d, sizeof(x));}
32 #define do(i, x) for(i = 0; i < x; i ++)
33 #define dod(i, x, l) for(i = x; i >= l; i --)
34 #define doe(i, x) for(i = 1; i <= x; i ++)
35 int n;
36 int a[MAXN], b[MAXN];
37 int mx_a[MAXN][MAXM], mi_b[MAXN][MAXM];
38 int p[MAXM], flog[MAXN];
39
40 void init()
41 {
42 p[0] = 1, flog[0] = -1;
43 for(int i = 1; i < MAXM; i ++) p[i] = 2 * p[i - 1];
44 for(int i = 1; i <= n; i ++) flog[i] = (i & (i - 1)) ? flog[i - 1] : (flog[i - 1] + 1);
45
46 for(int i = 1; i <= n; i ++) mx_a[i][0] = a[i];
47 for(int j = 1; j < MAXM; j ++)
48 for(int i = 1; i <= n; i ++)
49 if(i + p[j] - 1 <= n)
50 mx_a[i][j] = max(mx_a[i][j - 1], mx_a[i + p[j - 1]][j - 1]);
51
52 for(int i = 1; i <= n; i ++) mi_b[i][0] = b[i];
53 for(int j = 1; j < MAXM; j ++)
54 for(int i = 1; i <= n; i ++)
55 if(i + p[j] - 1<= n)
56 mi_b[i][j] = min(mi_b[i][j - 1], mi_b[i + p[j - 1]][j - 1]);
57 }
58
59 int get_mx_a(int l, int r)
60 {
61 int k = flog[r - l + 1];
62 return max(mx_a[l][k], mx_a[r - p[k] + 1][k]);
63 }
64
65 int get_mi_b(int l, int r)
66 {
67 int k = flog[r - l + 1];
68 return min(mi_b[l][k], mi_b[r - p[k] + 1][k]);
69 }
70
71 int min_l(int pos)
72 {
73 int l, r, mid;
74 l = pos - 1, r = n + 1;
75 while(r - l > 1)
76 {
77 mid = (l + r) >> 1;
78 if(get_mx_a(pos, mid) >= get_mi_b(pos, mid)) r = mid;
79 else l = mid;
80 }
81 return r;
82 }
83
84 int max_r(int pos)
85 {
86 int l, r, mid;
87 l = pos - 1, r = n + 1;
88 while(r - l > 1)
89 {
90 mid = (l + r) >> 1;
91 if(get_mx_a(pos, mid) > get_mi_b(pos, mid)) r = mid;
92 else l = mid;
93 }
94 return r;
95 }
96
97 int main()
98 {
99 scanf("%d", &n);
100 for(int i = 1; i <= n; i ++)
101 scanf("%d", &a[i]);
102 for(int i = 1; i <= n; i ++)
103 scanf("%d", &b[i]);
104
105 init();
106
107 LL ans = 0;
108 for(int i = 1; i <= n; i ++)
109 {
110 int l = min_l(i);
111 int r = max_r(i);
112 ans = ans + (r - l);
113 }
114 printf("%I64d\n", ans);
115 return 0;
116 }Problem_E(CodeForces 689E):
题意:
f([l, r])表示区间[l, r]内元素个数:r - l + 1
现在给n个区间, 求这n个区间任选k个, 将其求交集运算后的f值。
求出所有情况的f值之和。
思路:
先考虑每个点, 假设已知这个点被x个区间覆盖, 那么, 这个点被计算的次数就是C(x, k)次。
求出所有点的情况即可。 再拓展一下, 如果连续y个点的覆盖数是一样的, 那么就可以得出这y个点被计算的总次数是 y * C(x, k)
利用求前缀和的思路来处理这个点, 左右端点+-1.
这里左端点-1 其实是将整个区间往前移动了一下, 相当于是从0开始。
代码:
1 #include <cmath>
2 #include <cstdio>
3 #include <cstring>
4 #include <cstdlib>
5 #include <ctime>
6 #include <set>
7 #include <map>
8 #include <list>
9 #include <stack>
10 #include <queue>
11 #include <string>
12 #include <vector>
13 #include <fstream>
14 #include <iterator>
15 #include <iostream>
16 #include <algorithm>
17 using namespace std;
18 #define LL long long
19 #define INF 0x3f3f3f3f
20 #define MOD 1000000007
21 #define eps 1e-6
22 #define MAXN 200010
23 #define MAXM 100
24 #define dd {cout<<"debug"<<endl;}
25 #define pa {system("pause");}
26 #define p(x) {printf("%d\n", x);}
27 #define pd(x) {printf("%.7lf\n", x);}
28 #define k(x) {printf("Case %d: ", ++x);}
29 #define s(x) {scanf("%d", &x);}
30 #define sd(x) {scanf("%lf", &x);}
31 #define mes(x, d) {memset(x, d, sizeof(x));}
32 #define do(i, x) for(i = 0; i < x; i ++)
33 #define dod(i, x, l) for(i = x; i >= l; i --)
34 #define doe(i, x) for(i = 1; i <= x; i ++)
35 LL n, k;
36 LL f[MAXN];
37 LL fac[MAXN], fack[MAXN];
38 map <LL, LL> mp;
39 vector <LL> v;
40
41 LL qpow(LL x, LL k)
42 {
43 LL res = 1;
44 while(k)
45 {
46 if(k & 1) res = res * x % MOD;
47 x = x * x % MOD;
48 k >>= 1;
49 }
50 return res;
51 }
52
53 LL inv(LL a, LL x)
54 {
55 return qpow(a, x - 2);
56 }
57
58 LL C(LL n, LL m)
59 {
60 if(n < m || m < 0) return 0;
61 return ((fac[n] * fack[n - m] % MOD) * fack[m]) % MOD;
62 }
63
64 void init()
65 {
66 fac[0] = fack[0] = 1;
67 for(int i = 1; i < MAXN; i ++)
68 {
69 fac[i] = (fac[i - 1] * i) % MOD;
70 fack[i] = inv(fac[i], MOD);
71 }
72 mp.clear();
73 v.clear();
74 }
75
76 int main()
77 {
78 init();
79 LL l, r;
80 scanf("%lld %lld", &n, &k);
81 for(int i = 1; i <= n; i ++)
82 {
83 scanf("%lld %lld", &l, &r);
84 mp[l - 1] ++;
85 v.push_back(l - 1);
86
87 mp[r] --;
88 v.push_back(r);
89 }
90
91 sort(v.begin(), v.end());
92
93 LL ans = 0, num = 0, pre_pos = - 1e9 - 10, cnt_pos, len;
94 int vlen = v.size();
95 for(int i = 0; i < vlen; i ++)
96 {
97 cnt_pos = v[i];
98 len = cnt_pos - pre_pos;
99 if(num >= k)
100 ans = (ans + len * C(num, k) % MOD) % MOD;
101 if(pre_pos != cnt_pos)
102 {
103 pre_pos = cnt_pos;
104 num = num + mp[cnt_pos];
105 }
106 }
107 printf("%lld\n", ans);
108 return 0;
109 }