zoukankan      html  css  js  c++  java
  • codeforces Round 593(div. 2)


    A、Stones

    题意:

    给出三种石头分别$a$,$b$,$c$个,每次拿石头的时候只能拿$1$个第一种石头和$2$个第二种石头,或者$1$个第二种石头和$2$个第三种石头,求最多能拿到多少?

    题解:

    先考虑后一种方案:这样子一共拿了$min(b, c/2)*3$个石头,然后剩下的石头再取$min((b-c/2)/2,a)*3$.

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int main()
     4 {
     5     int n;
     6     scanf("%d", &n);
     7     while (n--)
     8     {
     9         int a, b, c;
    10         scanf("%d%d%d", &a, &b, &c);
    11         int ans = 0;
    12         while (b > 0 && c > 1)
    13         {
    14             ans += 3;
    15             b -= 1;
    16             c -= 2;
    17         }
    18         while (b > 1 && a > 0)
    19         {
    20             ans += 3;
    21             b -= 2;
    22             a -= 1;
    23         }
    24         printf("%d
    ", ans);
    25     }
    26     return 0;
    27 }
    View Code

    B、Alice and the List of Presents

    题意:

    给出无限个$n$种东西放进$m$个包且每个包中不出现重复元素的方案数,包里面可以不放东西。

    题解:

    考虑每个包里面都可以放或者不放某东西,一共$2^m-1$种,然后一共有$n$个物品,所以就是$(2^m-1)^n$种。

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const ll mod = 1e9 + 7;
     5 ll pow(ll a, ll b, ll p)
     6 {
     7     ll res = 1;
     8     while (b)
     9     {
    10         if (b & 1)
    11             res = res * a % p;
    12         a = a * a % p;
    13         b >>= 1;
    14     }
    15     return res;
    16 }
    17 int main()
    18 {
    19     ll n, m;
    20     scanf("%lld%lld", &n, &m);
    21     printf("%lld", pow((pow(2, m, mod) - 1ll + mod) % mod, n, mod));
    22     return 0;
    23 }
    View Code

    C、Labs

    题意:

    定义$f(X,Y)$是$X$集合中$a$,和$Y$集合中的$b$满足$a>b$的数对的数量。给出一个$n imes n$的矩阵,元素是$1~n^2$,求出一种填数方式,使得对于所有的行,最大的$f(X_i,X_j)$最小。

    题解:

    考虑要最大的最小,首先发现因为所有的数都不一样,所以$f(X,Y)+f(Y,X)=n*n$,则我们需要找到一种分法,使得所有的行之间的$max(f(X,Y),f(Y,X))$等于$frac {n*n}{2}$。所以,我们可以把这$n*n$个数按顺序分成$n$组,然后就第一组选$max$,第二组选$min$,第三组选$max$交替选够$n$个数,构成第一行,然后第二行从$min$选起,交替选够$n$个数,以此类推,观察矩阵的数可以发现规律,按规律写出代码即可。

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 3e2 + 5;
     4 int ans[N][N];
     5 int main()
     6 {
     7     int n;
     8     scanf("%d", &n);
     9     for (int i = 1; i <= n; ++i)
    10         for (int j = 1; j <= n; ++j)
    11             ans[i][j] = i + n * (j - 1);
    12     for (int i = 2; i <= n; i += 2)
    13         for (int j = 1; j <= n / 2; ++j)
    14             swap(ans[j][i], ans[n - j + 1][i]);
    15     for (int i = 1; i <= n; ++i)
    16         for (int j = 1; j <= n; ++j)
    17             printf("%d%c", ans[i][j], " 
    "[j == n]);
    18     return 0;
    19 }
    View Code

    D、Alice and the Doll

    题意:

    给出一个玩偶,它只能向前和向右,这个玩偶在$(1,1)$开始,走一个有障碍物的$n*m$的方格图,求能不能走完所有不是障碍物的格子。

    题解:

    理论上直接模拟就行,但是这样子时间复杂度是$O(n*m)$,所以我们预处理出每一行每一列所有障碍物,排好序,这样子就可以用二分查找找出前面的第一个障碍物。这样子时间就降到$O(nlogn)$了。

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e5 + 5;
     4 typedef long long ll;
     5 vector<int> G1[N];
     6 vector<int> G2[N];
     7 int main()
     8 {
     9     int n, m, k;
    10     scanf("%d%d%d", &n, &m, &k);
    11     for (int i = 1; i <= k; ++i)
    12     {
    13         int a, b;
    14         scanf("%d%d", &a, &b);
    15         G1[a].push_back(b);
    16         G2[b].push_back(a);
    17     }
    18     for (int i = 1; i <= n; ++i)
    19         sort(G1[i].begin(), G1[i].end());
    20     for (int i = 1; i <= m; ++i)
    21         sort(G2[i].begin(), G2[i].end());
    22     bool f = 0;
    23     ll ans = 1;
    24     int x = 1, y = 1;
    25     int up = 1, down = n, left = 1, right = m;
    26     int dir = 0;
    27     while (1)
    28     {
    29         int ny, nx;
    30         if (dir == 0) //右方向
    31         {
    32             int pos = lower_bound(G1[x].begin(), G1[x].end(), y) - G1[x].begin();
    33             nx = x;
    34             if (pos == G1[x].size())
    35                 ny = right;
    36             else
    37                 ny = min(right, G1[x][pos] - 1);
    38             up = x + 1;
    39         }
    40         else if (dir == 1) //下方向
    41         {
    42             int pos = lower_bound(G2[y].begin(), G2[y].end(), x) - G2[y].begin();
    43             ny = y;
    44             if (pos == G2[y].size())
    45                 nx = down;
    46             else
    47                 nx = min(down, G2[y][pos] - 1);
    48             right = y - 1;
    49         }
    50         else if (dir == 2)
    51         {
    52             int pos = lower_bound(G1[x].begin(), G1[x].end(), y) - G1[x].begin() - 1;
    53             nx = x;
    54             if (pos < 0)
    55                 ny = left;
    56             else
    57                 ny = max(left, G1[x][pos] + 1);
    58             down = x - 1;
    59         }
    60         else if (dir == 3)
    61         {
    62             int pos = lower_bound(G2[y].begin(), G2[y].end(), x) - G2[y].begin() - 1;
    63             ny = y;
    64             if (pos < 0)
    65                 nx = up;
    66             else
    67                 nx = max(up, G2[y][pos] + 1);
    68             left = y + 1;
    69         }
    70         if (nx == x && ny == y && f)
    71             break;
    72         dir = (dir + 1) % 4;
    73         ans += abs(nx - x) + abs(ny - y);
    74         x = nx;
    75         y = ny;
    76         f = 1;
    77     }
    78     if (ans == (ll)n * m - k)
    79         printf("Yes
    ");
    80     else
    81         printf("No
    ");
    82     return 0;
    83 }
    View Code

    E、Alice and the Unfair Game

    题意:

    给出$n$的盒子,其中有一个盒子有宝物,$A$会给出一个位置$pos$,如果猜对了就赢了,为了防止赢,在$A$猜了之后,宝物可以向相邻的盒子转移,设开始时宝物在$x$,猜$m$次之后在$y$,求$(x,y)$的数量。

    题解:

    这样的问题通pos_i常建图解决,实际上就是求从起点开始走了$m$步之后到达的位置的集合。但是这里因为它只能向相邻盒子走,所以我们直接扩展出$(m+2) imes n$的矩阵,$(i,pos_i)$表示障碍,找到从$(0,x)$走到$(m+1,y)$的路径数就是答案,显然,找出从一个点贪心向左走或者贪心向右走的区间后,区间内的所有位置都可达。然后可以得到$l_{a_i+i}=l_{a_i+i+1}+1$,$r_i$同理,因为考虑到可能存在$i$和$j$使得$i+a_i=j+a_j$,则需要倒序枚举。然后再对每一个点$(0,x)$求出在第$m+1$行的范围,累加即可。

    AC代码:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 1e5 + 5;
     4 typedef long long ll;
     5 int a[N], l[N << 2], r[N << 2];
     6 const int offset = 1e5;
     7 int main()
     8 {
     9     int n, m;
    10     scanf("%d%d", &n, &m);
    11     for (int i = 1; i <= m; ++i)
    12         scanf("%d", &a[i]);
    13     if (n == 1)
    14         return printf("0
    "), 0;
    15     for (int i = m; i >= 1; --i)
    16     {
    17         l[a[i] - i + offset] = l[a[i] - i - 1 + offset] + 1;
    18         r[a[i] + i + offset] = r[a[i] + i + 1 + offset] + 1;
    19     }
    20     ll ans = 0;
    21     for (int i = 1; i <= n; ++i)
    22     {
    23         int rr = min(n, i + m + 1 - l[i + offset]);
    24         int ll = max(1, i - m - 1 + r[i + offset]);
    25         ans += rr - ll + 1;
    26     }
    27     printf("%lld
    ", ans);
    28     return 0;
    29 }
    View Code
  • 相关阅读:
    Android操作系统中11种传感器的介绍【转】
    陀螺仪、加速计、磁力计【转】
    【转】在ubuntu环境下搭建svn server遇到的一些问题
    【转】Ubuntu下搭建SVN环境-Apache
    【转】Java ConcurrentModificationException 异常分析与解决方案--还不错
    【转】ConcurrentModificationException异常解决办法 --不错
    【转】Java ConcurrentModificationException异常原因和解决方法
    【转】 为SeekBar滑块设置固定值以及自定义Seekbar,progressbar样式--不错
    【转】Android自定义Adapter的ListView的思路及代码
    【转】如何开发苹果iOS操作平台下的应用程序?
  • 原文地址:https://www.cnblogs.com/Aya-Uchida/p/13266242.html
Copyright © 2011-2022 走看看