Codeforces Round #361 div2

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 }

时间: 2024-08-28 23:09:21

Codeforces Round #361 div2的相关文章

codeforces round #257 div2 C、D

本来应该认真做这场的,思路都是正确的. C题,是先该横切完或竖切完,无法满足刀数要求,再考虑横切+竖切(竖切+横切), 因为横切+竖切(或竖切+横切)会对切割的东西产生交叉份数,从而最小的部分不会尽可能的大. 代码如下,虽然比较长.比较乱,但完全可以压缩到几行,因为几乎是4小块重复的代码,自己也懒得压缩 注意一点,比如要判断最小块的时候,比如9行要分成2份,最小的剩下那份不是9取模2,而应该是4 m/(k+1)<=m-m/(k+1)*k          #include<bits/stdc+

codeforces Round #250 (div2)

a题,就不说了吧 b题,直接从大到小排序1-limit的所有数的lowbit,再从大到小贪心组成sum就行了 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #define N 200000 6 using namespace std; 7 int pos[N],a[N],s[N],f[N],la[N],b[N],i,j,k,ans,n,p

Codeforces Round#320 Div2 解题报告

Codeforces Round#320 Div2 先做个标题党,骗骗访问量,结束后再来写咯. codeforces 579A Raising Bacteria codeforces 579B Finding Team Member codeforces 579C A Problem about Polyline codeforces 579D "Or" Game codeforces 579E Weakness and Poorness codeforces 579F LCS Aga

Codeforces Round #254(div2)A

很有趣的题.想到了就非常简单,想不到就麻烦了. 其实就是一种逆向思维:最后结果肯定是这样子: WBWBWBWB... BWBWBWBW... WBWBWBWB... ... 里面有“-”的地方改成“-”就行了. 但是我开始是正着想的,想每个点怎么处理,这还要看它周围点的状态,越想越麻烦... 这题中体现的正难则反的逆向思维很值得学习. #include<iostream> #include<cstdio> #include<cstdlib> #include<cs

Codeforces Round #254(div2)B

就是看无向图有几个连通块,答案就是2n-num. 范围很小,就用矩阵来存图减少代码量. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> #include<set> #include<vector> #include<algorithm> #inc

Codeforces Round #260(div2)C(递推)

有明显的递推关系: f[i]表示i为数列中最大值时所求结果.num[i]表示数i在数列中出现了几次. 对于数i,要么删i,要么删i-1,只有这两种情况,且子问题还是一样的思路.那么很显然递推一下就行了:f[i]=max(f[i-1],f[i-2]+i*num[i]); 这里技巧在于:为了防止麻烦,干脆就所有数的出现次数都记录一下,然后直接从2推到100000(类似于下标排序),就不用排序了,也不用模拟删除操作了.这一技巧貌似简单,但实际上临场想出来也需要点水平. #include<iostrea

Codeforces Round #289 Div2 E

Problem 给一串长度为N的字符串,对于每个字符,若字符为元音,则权值为1,否则为0.一个子串的权值定义为该串所有字符权值之和除以字符个数,一个母串的权值定义为所有子串的权值之和.求母串的权值. Limits Time Limit(ms): 1000 Memory Limit(MB): 256 N: [1, 5*10^5] 字符集: 'A'-'Z' 元音: I E A O U Y Solution 考虑每个元音字符对母串的贡献,可以找出规律. More 举"ABCDOEFGHKMN"

Codeforces Round #403 div2 C. Andryusha and Colored Balloons

题目链接:Codeforces Round #403 div2 C. Andryusha and Colored Balloons 题意: 给你一棵n个节点的树,然后让你染色,规定相连的三个 节点不能同色,问需要的最少颜色,并输出其中一种方案. 题解: 因为只有相邻3个节点不同色. 所以直接DFS,每个节点都从1开始. 然后ans[v]!=ans[u]!=ans[fa]就行. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i&

CodeForces Round#229 DIV2 C 递推DP

对这道题目也只好说呵呵了,没注意k的范围最大才10,所以昨晚纠结了很久,没什么好的方法来处理,后来无奈想去翻翻题解,发现人家开头就来了句,因为k的范围比较小 所以.........我只好暂停马上回头看看题目,是的,k比较小所以完全可以先在询问前预处理DP一遍, DP就比较清晰了,dp[i][j]  (i>=0 && i<k,,,,j>=i && j <=n)代表意义呢 以i为开头的  区间[1,j]注意 是 1~j的 所需要的操作数,题目问的是最小操