• 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
    ", x);}
    27 #define pd(x) {printf("%.7lf
    ", 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
    " : "YES
    ");
    63 }
    64 
    65 int main()
    66 {
    67     scanf("%d", &n);
    68     scanf("%s", str);
    69     
    70     get_ans();
    71     return 0;
    72 }
    View Code

    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
    ", x);}
     27 #define pd(x) {printf("%.7lf
    ", 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("
    ");
     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 }
    View Code

    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
    ", x);}
    27 #define pd(x) {printf("%.7lf
    ", 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
    ");
    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);
    79     }
    80     return 0;
    81 }
    View Code

    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
    ", x);}
     27 #define pd(x) {printf("%.7lf
    ", 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
    ", ans);
    115     return 0;
    116 }
    View Code

    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
    ", x);}
     27 #define pd(x) {printf("%.7lf
    ", 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
    ", ans);
    108     return 0;
    109 }
    View Code
  • 相关阅读:
    Qt之等待提示框(QTimer)
    Qt之等待提示框(QPropertyAnimation)
    FormatUtil类型格式转换
    FirstLetterUtil
    文件上传下载
    file相关的操作,(md5,word转html,复制,删除等)
    SessionListener失败,退出
    JackJson的一些方法
    全局常量
    session用户账号认证(一个用户登陆,踢出前一个用户)
  • 原文地址:https://www.cnblogs.com/By-ruoyu/p/5666735.html
Copyright © 2020-2023  润新知