zoukankan      html  css  js  c++  java
  • 【ATcoder】AtCoder Beginner Contest 161 题解

    题目链接:AtCoder Beginner Contest 161

    原版题解链接:传送门

    A - ABC Swap

    这题太水,直接模拟即可。

     1 #include <iostream>
     2 using namespace std;
     3 int main() {
     4     int a, b, c;
     5     cin >> a >> b >> c;
     6     swap(a, b);
     7     swap(a, c);
     8     cout << a << " " << b << " " << c << endl;
     9     return 0;
    10 }
    STL版
     1 #include <iostream>
     2 using namespace std;
     3 int main() {
     4     int a, b, c, tmp;
     5     cin >> a >> b >> c;
     6     tmp = a;
     7     a = b;
     8     b = tmp;
     9     tmp = a;
    10     a = c;
    11     c = tmp;
    12     cout << a << " " << b << " " << c << endl;
    13     return 0;
    14 }
    手写版

    B - Popular Vote

    这题也很水!(这次ABC都挺水)

    求出那个题目要求的值,然后对序列排序,从大到小枚举看有多少个不小于,最后与 $m$ 比较即可。

    此题需要double,其实向上取整也可以。

     1 #include <iostream>
     2 #include <algorithm>
     3 using namespace std;
     4 int n, m, a[1000], sum;
     5 int main() {
     6     cin >> n >> m;
     7     for (int i = 1; i <= n; i++) {
     8         cin >> a[i];
     9         sum += a[i];
    10     }
    11     sum = (sum + 4 * m - 1) / (4 * m);//向上取整
    12     sort(a + 1, a + n + 1);
    13     for (int i = n; i >= 1; i--) {
    14         if (a[i] >= sum) {
    15             m--;
    16         } else {
    17             break;
    18         }
    19     }
    20     if (m > 0) puts("No");
    21     else puts("Yes");
    22     return 0;
    23 }
    B

    C - Replacing Integer

    我们对问题进行分类讨论。

    (1)若 $n leq k$,则只会出现两种情况:$n 或 k-n$(因为 $k-(k-n)=n$,有循环回来了),输出较小值即可。

    (2)否则,$n$ 会一直减 $k$,一直减到 $n < k$时,这个过程最终得到的其实就是 $n模k$,然后就到了(1)。

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <map>
     4 #include <cmath>
     5 using namespace std;
     6 typedef long long ll;
     7 ll n, k;
     8 ll F(ll n, ll k) {
     9     if (n <= k) {
    10         return min(n, k - n);
    11     }
    12     return F(n % k, k);
    13 }
    14 int main() {
    15     cin >> n >> k;
    16     cout << F(n, k);
    17     return 0;
    18 }
    C

    D - Lunlun Number

    此题本人是用 $dp+构造$ 做的。

    设 $dp[i][j]$ 代表以 $i$ 开头,有 $j$ 位的lunlun数有多少个。

    根据样例的提示,其实 $j$ 最大也就 $10$。$i$ 在 $[0,9]$。

    首先初始化所有 $dp[i][1]=1$。

    然后不难想到转移方程 $dp[i][j]=dp[i-1][j-1]+dp[i][j-1]+dp[i+1][j-1]$。

    当然如果 $i=0或i=9$ 时要特殊处理(具体见代码)。

    接下来开始构造。

    首先算出第 $k$ 个数的位数。

    这很好办,我们只用统计每个位数有多少lunlun数,然后做一遍前缀和,从小到大遍历,找到第一个大于等于 $k$ 的位数即为 $k$ 的位数。

    确定好位数之后我们就可以开始枚举每一位是什么了。

    当然不是暴力枚举。

    如果是第一位,我们暴力枚举 $1-9$,用找位数同样的方法,我们可一个确定第一个位置的数(我们记录了以 $i$ 开头,有 $j$ 位的lunlun数有多少个)。

    然后后面的位置的数只有最多三种选择——上次减一,上次同样和上次加一(记住不能小于 $0$ 或大于 $9$)。

    然后再用相同的方法即可。

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <map>
     4 #include <cmath>
     5 using namespace std;
     6 typedef long long ll;
     7 ll dp[10][20];//dp[i][j]代表以i开头的j位数有多少个lunlun 
     8 ll sum[20], pos;
     9 ll k;
    10 void dfs(ll num, ll lst) {
    11     if (num > pos) return;
    12     if (num == 1) {
    13         for (ll i = 1; i < 10; i++) {
    14             if (k > dp[i][pos - num + 1]) {
    15                 k -= dp[i][pos - num + 1];
    16             } else {
    17                 cout << i;
    18                 dfs(num + 1, i);
    19                 break;
    20             }
    21         }
    22     } else {
    23         for (ll i = lst - 1; i <= lst + 1; i++) {
    24             if (i < 0 || i > 9) continue;//记住特判 
    25             if (k > dp[i][pos - num + 1]) {
    26                 k -= dp[i][pos - num + 1];
    27             } else {
    28                 cout << i;
    29                 dfs(num + 1, i);
    30                 break;
    31             }
    32         }
    33     }
    34 }
    35 int main() {
    36     cin >> k;
    37     for (ll i = 0; i < 10; i++) {
    38         dp[i][1] = 1;
    39     }
    40     sum[1] = 9;
    41     for (ll j = 2; j <= 10; j++) {
    42         for (ll i = 0; i < 10; i++) {
    43             if (i != 0 && i != 9) dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1] + dp[i + 1][j - 1];
    44             else if (i != 0) dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1];
    45             else if (i != 9) dp[i][j] = dp[i][j - 1] + dp[i + 1][j - 1];
    46             if (i != 0) sum[j] += dp[i][j];
    47         }
    48     }
    49     for (ll i = 1; i <= 20; i++) {
    50         if (k > sum[i]) {
    51             k -= sum[i];
    52         } else {
    53             pos = i;
    54             break;
    55         }
    56     }
    57     dfs(1, 0);
    58     return 0;
    59 }
    D

    E - Yutori

    这题显然可以贪心。

    正这做一遍反着做一遍,如果两遍都要某一个点的话那个点就是答案。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <stack>
     4 using namespace std;
     5 typedef long long ll;
     6 ll n, k, c, lst;
     7 bool flag;
     8 string s;
     9 ll cnt;
    10 bool vis[200010];
    11 stack<int> stk;
    12 int main() {
    13     cin >> n >> k >> c;
    14     cin >> s;
    15     lst = -1;
    16     for (int i = 0; i < (int)(s.length()); i++) {
    17         if (s[i] == 'x' || lst >= i) continue;
    18         if (cnt >= k) {
    19             flag = 1;
    20             break;
    21         }
    22         lst = i + c;
    23         vis[i] = 1;
    24         cnt++;
    25     }
    26     if (flag) {
    27         return 0;
    28     }
    29     lst = s.length();
    30     for (int i = (int)s.length() - 1; i >= 0; i--) {
    31         if (s[i] == 'x' || lst <= i) continue;
    32         lst = i - c;
    33         if (vis[i]) {
    34             stk.push(i);
    35         }
    36     }
    37     while (!stk.empty()) {
    38         cout << stk.top() + 1 << endl;;
    39         stk.pop();
    40     }
    41     return 0;
    42 } 
    E

    F - Division or Substraction

    我觉得这题应该和E换换位置。

    首先这题有两种情况:

    1 不是 $n$ 的约数

    这种情况比较简单,不是 $n$ 的约数根据题意 $n$ 会一直减 $k$,减到 $n<k$。

    最后得到的其实就是 $n模k$(好像和C有点像)。

    我们需要找的其实就是所有 $k$ 使得 $n模k=1$。

    这其实就是 $n-1$ 的约数,所以直接查询 $n-1$ 的约数(不包括1)个数即可。时间复杂度:$O(sqrt{n})$

    2 是 $n$ 的约数

    这种情况其实更好想。

    我们首先要找到所有约数(不包括1),这样做的复杂度是$O(sqrt{n})$

    根据题目要求我们要不断的除以这个约数,而因为 $k geq 2$ 所以这是$O(log{n})$ 的。

    而当它不整除时,就变成了1,得到的会是 $n模k$(此时的 $n$ 应是除以 $k$ 若干遍后的 $n$),如果 $n模k==1$ 则 $ans++$。

    总复杂度 $O(sqrt{n} imes log{sqrt{n}})$。

    记得 $n$ 一定是一个满足条件的 $k$。

    记住要特判“2”。

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <map>
     4 #include <cmath>
     5 using namespace std;
     6 typedef long long ll;
     7 ll n;
     8 ll F(ll x) {
     9     ll ret = 1;
    10     for (ll i = 2; i * i <= x; i++) {
    11         if (x % i == 0) {
    12             ret += 2;
    13             if (x / i == i) ret--;
    14         }
    15     }
    16     return ret;
    17 }
    18 ll G(ll x) {
    19     ll ret = 1, tp;
    20     for (ll i = 2; i * i <= x; i++) {
    21         if (x % i == 0) {
    22             ll tmp = x / i;
    23             tp = x;
    24             while (tp % i == 0) {
    25                 tp /= i;
    26             }
    27             if (tp > i) tp %= i;
    28             ret += (tp == 1);
    29             if (tmp != i) {
    30                 tp = x;
    31                 while (tp % tmp == 0) {
    32                     tp /= tmp;
    33                 }
    34                 if (tp > tmp) tp %= tmp;
    35                 ret += (tp == 1);
    36             }
    37         }
    38     }
    39     return ret;
    40 }
    41 int main() {
    42     cin >> n;
    43     if (n == 2) {
    44         cout << 1;
    45         return 0;
    46     }
    47     cout << F(n - 1) + G(n);
    48     return 0;
    49 }
    F
  • 相关阅读:
    node nmp 的关键信息
    PHP中定义常量的区别,define() 与 const
    mac电脑如何快速显示桌面及切换应用
    Mac拷贝/复制文件夹路径快捷键
    比 file_get_contents() 更优的 cURL 详解(附实例)
    PHP fopen/file_get_contents与curl性能比较
    在phpstorm中如何对比文件呢?
    PHP 基础篇
    MySQL 中视图和表的区别以及联系是什么?
    MAC将根目录文件夹的权限赋给用户
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/12634639.html
Copyright © 2011-2022 走看看