AtCoder ABC215简易题解

这篇博客详细解析了ABC215比赛中的六道题目,包括判断字符串是否为'Hello,World!',寻找满足条件的整数k,求字符串的第k小字典序排列,找出与数组元素互质的数,解决位DP问题以及使用二分查找求解最大问题的最小值。内容涵盖了字符串操作、质数筛选、全排列、数论及搜索算法等编程知识点。
摘要由CSDN通过智能技术生成

#链接
https://atcoder.jp/contests/abc215/tasks

A 题

链接

https://atcoder.jp/contests/abc215/tasks/abc215_a

题解

签到水题。
给一个字符串,判断是否是 Hello,World!。

AC代码

#include <bits/stdc++.h>
 
using namespace std;
 
typedef long long LL;
typedef pair<LL, LL> PLL;
 
const LL INF=4e18;
const int MAXN=1e6+10;
 
int main() {
#if 0
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
#endif
#if 0
    freopen("00.in", "r", stdin);
    freopen("00.out", "w", stdout);
#endif
    string s;
    getline(cin, s);
    if (s=="Hello,World!") {
        cout<<"AC\n";
    } else {
        cout<<"WA\n";
    }
 
    return 0;
}

B 题

链接

https://atcoder.jp/contests/abc215/tasks/abc215_b

题解

给一个 n n n,找最大的整数 k k k,满足 2 k ≤ n 2^k \leq n 2kn
由于本题的 n n n 很小,只有 1 0 18 10^{18} 1018,因此可以使用暴力求解。

AC 代码

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<LL, LL> PLL;

const LL INF=4e18;
const int MAXN=1e6+10;

int main() {
#if 1
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
#endif
#if 0
    freopen("00.in", "r", stdin);
    freopen("00.out", "w", stdout);
#endif
    LL n;
    cin>>n;
    LL k=0;
    LL ans=1;
    while (ans<=n) {
        k++;
        ans*=2;
    }
    cout<<k-1<<"\n";

    return 0;
}

C题

链接

https://atcoder.jp/contests/abc215/tasks/abc215_c

题解

给一个字符串 S S S,求第 K K K 小的字典序字符串。
本题的 S S S 长度只有 8 8 8,也就意味着最多是 8 ! = 40 , 320 8!=40,320 8!=40,320 种答案。因此,我们只需要列出所有的全排列,然后输出第 K K K 小的即可。
最简单的方法就是使用 STL 的 next_permutation() 函数。当然也可以使用 dfs 来解。

AC代码

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<LL, LL> PLL;

const LL INF=4e18;
const int MAXN=1e5+10;
string ans[MAXN];

int main() {
#if 1
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
#endif
#if 0
    freopen("00.in", "r", stdin);
    freopen("00.out", "w", stdout);
#endif
    string s;
    LL K;
    cin>>s>>K;
    sort(s.begin(), s.end());

    LL cnt=0;
    do {
        ans[++cnt]=s;
        //cout<<s<<"\n";
    } while (next_permutation(s.begin(), s.end()));
    //cout<<cnt<<"\n";
    cout<<ans[K]<<"\n";
    return 0;
}

D题

链接

https://atcoder.jp/contests/abc215/tasks/abc215_d

题解

N N N 个正整数 A 1 ,   A 2 ,   … ,   A N A_1,\ A_2,\ \dots,\ A_N A1, A2, , AN,找出所有从 1 1 1 k k k,满足 gcd ( A i , k ) = 1 \text{gcd}(A_i, k)=1 gcd(Ai,k)=1
本题要求找出任意一个 k k k 和数组 A A A 的所有元素互质。
如果本题使用暴力求解,即枚举所有的 1 ∼ m 1 \sim m 1m 中的所有数据,使得其满足题目要求。但是由于 n ,   m n,\ m n, m 的大小为 1 0 5 10^5 105,这个算法的时间复杂度为 O ( m ∗ n ) O(m*n) O(mn),因此最大情况需要计算 1 0 5 ∗ 1 0 5 = 1 0 10 10^5 *10^5=10^{10} 105105=1010,这样的计算量即使是 2 2 2s 也是要超时的。
注意到本题的 A i A_i Ai 取值范围是 1 ∼ 1 0 5 1 \sim 10^5 1105,也就是说这个值域非常小。所以我们可以先用筛法筛出 1 0 5 10^5 105 中所有质数。然后再遍历 m m m

AC代码

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<LL, LL> PLL;
const int MAXN=1e5+10;
vector<bool> exist(MAXN, false);//数据i是否出现
vector<bool> ispri(MAXN, true);//数据i是否是质数

int main() {
#if 1
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
#endif
#if 0
    freopen("00.in", "r", stdin);
    freopen("00.out", "w", stdout);
#endif
   LL n,m;
   cin>>n>>m;

   //筛法初始化
   ispri[0]=ispri[1]=false;//质数

   for (LL i=1; i<=n; i++) {
      LL val;
      cin>>val;
      exist[val]=true;
   }

   //找出范围内所有质数
   for (LL i=2; i<MAXN; i++) {
      if (!ispri[i]) {
         exist[i]=false;
         continue;
      }
      for (LL j=i; j<MAXN; j+=i) {
         ispri[j]=false;
         if (exist[j]) {
            exist[i]=true;
            break;
         }
      }
   }

   //遍历可能的结果
   vector<bool> possible(m+1, true);
   possible[0]=false;
   for (LL i=2; i<=m; i++) {
      if (!exist[i]) {
         continue;
      }
      for (LL j=i; j<=m; j+=i) {
         possible[j]=false;
      }
   }

   LL cnt=0;
   for (LL i=1; i<=m; i++) {
      if (possible[i]) {
         cnt++;
      }
   }
   cout<<cnt<<"\n";
   for (LL i=1; i<=m; i++) {
      if (possible[i]) {
         cout<<i<<"\n";
      }
   }

   return 0;
}

E题

链接

https://atcoder.jp/contests/abc215/tasks/abc215_e

题解

这题是竞赛后完成的。阅读完后,这题是一个 bit DP 题目。惨,bit DP 早就忘记了。还好,本题算 bit DP 的模板题,直接套用模板即可。
对应的状态方程如下:
d p [ i ] [ u ] [ j ] = d p [ i − 1 ] [ u ] [ j ] dp[i][u][j]=dp[i-1][u][j] dp[i][u][j]=dp[i1][u][j]
其中: i i i 表示竞赛的编号, u u u 表示所有的集合, j j j 表示竞赛的种类。

AC代码

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int MAXN=1024;
LL dp[MAXN][MAXN][12];

const LL MOD=998244353;

int main(){
#if 1
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
#endif
   LL n;
   string s;
   cin>>n>>s;

   for(LL i=1;i<=n;i++){
      LL x=s[i-1]-'A';
      for(LL u=0; u<MAXN;u++){
         for(LL j=0;j<10;j++){
            dp[i][u][j]=dp[i-1][u][j];
            if(j==x){
               dp[i][u][j]+=dp[i-1][u][j];
               dp[i][u][j]%=MOD;
            }
         }
      }

      for(LL v=0;v<MAXN;v++){
         if(v&(1<<x)){
            continue;
         }
         for(LL j=0;j<10;j++){
            dp[i][v|(1<<x)][x]+=dp[i-1][v][j];
            dp[i][v|(1<<x)][x]%=MOD;
         }
      }

      dp[i][(1<<x)][x]++;
      dp[i][(1<<x)][x]%=MOD;
   }

   LL res=0;
   for(LL u=0;u<MAXN;u++){
      for(LL j=0;j<10;j++){
         res+=dp[n][u][j];
         res%=MOD;
      }
   }
   cout << res << '\n';

   return 0;
}

F题

链接

https://atcoder.jp/contests/abc215/tasks/abc215_f

题解

吐槽一下,F 题竟然比 E 题简单。
题目要求我们找所有最大问题的最小值,直接使用二分答案即可。
根据题目可知: min ( ∣ x i − y i ∣ ,   ∣ x j − y j ∣ ) ≥ K → ∣ x i − y i ∣ ≥ K  &&  ∣ x j − y j ∣ ≥ K \text{min}(|x_i-y_i|,\ |x_j-y_j|) \geq K \rightarrow |x_i-y_i| \geq K\ \text{\&\&}\ |x_j-y_j| \geq K min(xiyi, xjyj)KxiyiK && xjyjK

AC代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> PLL;
const LL INF=4e18;

int main(){
#if 1
   ios::sync_with_stdio(0);
   cin.tie(0);
   cout.tie(0);
#endif
   LL n; 
   cin >> n;
   vector<PLL> v(n);
   for (LL i = 0; i < n; i++) {
      cin >> v[i].first >> v[i].second;
   }
   sort(v.begin(), v.end());

   LL ok = 0, ng = INF;
   while(ng - ok > 1){
      LL md = (ok + ng)/2;
      queue<PLL> que;
      bool able = false;
      LL mi = INF, ma = 0;
      for (auto p:v){
         while(!que.empty()){
            if(que.front().first > p.first - md) {
               break;
            }
            mi = min(mi, que.front().second); 
            ma = max(ma, que.front().second);
            que.pop();
         }
         if(mi <= p.second - md || ma >= p.second + md) {
            able=true;
         }
         que.push(p);
      }
      if(able) {
         ok = md;
      } else {
         ng = md;
      }
   }
   cout << ok << endl;
   return 0;
}

总结

我太难了,所有的东西都忘记了。人生艰难,连 ABC 都没法 AK 了。惨。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
AtCoder Beginner Contest 134 是一场 AtCoder 的入门级比赛,以下是每道题的简要题解: A - Dodecagon 题目描述:已知一个正十二边形的边长,求它的面积。 解题思路:正十二边形的内角为 $150^\circ$,因此可以将正十二边形拆分为 12 个等腰三角形,通过三角形面积公式计算面积即可。 B - Golden Apple 题目描述:有 $N$ 个苹果和 $D$ 个盘子,每个盘子最多可以装下 $2D+1$ 个苹果,求最少需要多少个盘子才能装下所有的苹果。 解题思路:每个盘子最多可以装下 $2D+1$ 个苹果,因此可以将苹果平均分配到每个盘子中,可以得到最少需要 $\lceil \frac{N}{2D+1} \rceil$ 个盘子。 C - Exception Handling 题目描述:给定一个长度为 $N$ 的整数序列 $a$,求除了第 $i$ 个数以外的最大值。 解题思路:可以使用两个变量 $m_1$ 和 $m_2$ 分别记录最大值和次大值。遍历整个序列,当当前数不是第 $i$ 个数时,更新最大值和次大值。因此,最后的结果应该是 $m_1$ 或 $m_2$ 中较小的一个。 D - Preparing Boxes 题目描述:有 $N$ 个盒子和 $M$ 个物品,第 $i$ 个盒子可以放入 $a_i$ 个物品,每个物品只能放在一个盒子中。现在需要将所有的物品放入盒子中,每次操作可以将一个盒子内的物品全部取出并分配到其他盒子中,求最少需要多少次操作才能完成任务。 解题思路:首先可以计算出所有盒子中物品的总数 $S$,然后判断是否存在一个盒子的物品数量大于 $\lceil \frac{S}{2} \rceil$,如果存在,则无法完成任务。否则,可以用贪心的思想,每次从物品数量最多的盒子中取出一个物品,放入物品数量最少的盒子中。因为每次操作都会使得物品数量最多的盒子的物品数量减少,而物品数量最少的盒子的物品数量不变或增加,因此这种贪心策略可以保证最少需要的操作次数最小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值