Educational Codeforces Round 139 (Rated for Div. 2)A~D题解

本文解析了四个算法题目,包括寻找特定数字、字符串操作验证、路径遍历判定及最大次数求解,提供了清晰的思路与代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

A

题意:让我们找到1~n中所有只有一位是非0数的个数。
思路:比较简单直接上代码

#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 1e6 + 10;
int a[N];

bool f(int x)
{
     int sum = 0;
     while (x)
     {
          int k = x % 10;
          if (k > 0)
               sum++;
          x /= 10;
     }
     if (sum == 1)
          return true;
     return false;
}

void solve()
{
     int n;
     cin >> n;
     cout << a[n] << endl;
}

int main()
{
     ios::sync_with_stdio(false);
     cin.tie(0);
     cout.tie(0);
     int T;
     cin >> T;
     for (int i = 1; i <= 1000000; i++)
     {
          if (f(i))
               a[i] = a[i - 1] + 1;
          else
               a[i] = a[i - 1];
     }
     while (T--)
     {
          solve();
     }
     return 0;
}

B

题意:给我们由n个字符组成的字符串,我们可以进行一个操作就是一个字符一个字符(任意字符)的插入,和把前面相邻的已经插入的k个字符复制一下插到结尾,问我们能不能在小于n次操作中得到给出的字符串。
思路:就是找一下有没有相同的子串。注意三个完全相同的要特殊处理一下。

#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;

unordered_map<string, bool> mp;

void solve()
{
     mp.clear();
     int n;
     cin >> n;
     string s;
     cin >> s;
     for (int i = 0; i < (int)s.size() - 1; i++)
     {
          string ss = s.substr(i, 2);
          if (s[i] == s[i + 1] && s[i - 1] == s[i] && s[i + 2] != s[i])
               continue;
          if (mp[ss])
          {
               cout << "YES" << endl;
               return;
          }
          mp[ss] = true;
     }
     cout << "NO" << endl;
}

int main()
{
     ios::sync_with_stdio(false);
     cin.tie(0);
     cout.tie(0);
     int T;
     cin >> T;
     while (T--)
     {
          solve();
     }
     return 0;
}

C

题意:给我们只有两个由W和B组成的字符串,然后每一列至少有一个“B”,问我们在不能走重复的点并且只走B的情况下,能不能把所有的B都走到。
思路:我们模拟一下并且计数比较一下即可。

#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;

const int N = 2e5 + 10;
int n;
char s[3][N];
bool st[3][N];
int nex, ney, nowx, nowy;
int dx[4] = {0, 0, 0, 1};
int dy[4] = {0, 1, -1, 0};

int bfs(int x, int y)
{
     int sum = 1;
     st[x][y] = true;
     while (true)
     {
          int k = false;
          if (y > n)
          {
               return sum;
          }
          if (x == 1)
          {
               if (s[2][y] == 'B' && st[2][y] == false)
               {
                    st[2][y] = true;
                    x = 2;
                    sum++;
                    k = true;
               }
               else if (s[x][y + 1] == 'B' && st[x][y + 1] == false)
               {
                    st[x][y + 1] = true;
                    y = y + 1;
                    sum++;
                    k = true;
               }
          }
          else if (x == 2)
          {
               if (s[1][y] == 'B' && st[1][y] == false)
               {
                    st[1][y] = true;
                    x = 1;
                    sum++;
                    k = true;
               }
               else if (s[x][y + 1] == 'B' && st[x][y + 1] == false)
               {
                    st[x][y + 1] = true;
                    y = y + 1;
                    sum++;
                    k = true;
               }
          }
          if (k == false)
          {
               break;
          }
     }
     return sum;
}

void solve()
{
     cin >> n;
     for (int i = 1; i <= 2; i++)
     {
          cin >> s[i] + 1;
     }
     int cnt = 0;
     for (int i = 1; i <= 2; i++)
     {
          for (int j = 1; j <= n; j++)
          {
               if (s[i][j] == 'B')
                    cnt++;
          }
     }
     if (n == 1)
     {
          cout << "YES" << endl;
     }
     else
     {
          memset(st, false, sizeof st);
          int flag = 0;
          if (s[1][1] == 'B')
          {
               int sum = bfs(1, 1);
               if (sum == cnt)
               {
                    cout << "YES" << endl;
                    return;
               }
          }
          memset(st, false, sizeof st);
          if (s[2][1] == 'B')
          {
               int sum = bfs(2, 1);
               if (sum == cnt)
               {
                    cout << "YES" << endl;
                    return;
               }
          }
          cout << "NO" << endl;
     }
}

int main()
{
     ios::sync_with_stdio(false);
     cin.tie(0);
     cout.tie(0);
     int T;
     cin >> T;
     while (T--)
     {
          solve();
     }
     return 0;
}

D

题意 :给我们两个数x和y问我们把他们同时加上1使他们gcd(x,y)=1最大可以加几次。
思路:本题我们可以证明出 g c d ( x + k , y + k ) = g c d ( x + k , y − x ) gcd(x+k,y+k) = gcd(x+k,y-x) gcd(x+k,y+k)=gcd(x+k,yx) 如果对此有疑问的话可以看一下官方题解讲的非常的详细也很好理解(传送门)然后我们得到上面的结论之后我们就可以求出(y-x)的质因数,然后所有质因数的倍数>x的那个并且是最小的我们设N,然后N-x就是我们的答案。
这个题求质因数的方法值得学习

#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;

const int N = 1e7 + 10;
int a[N];
int mind[N];

vector<int> v;

void init()
{
     for (int i = 0; i < N; i++)
          mind[i] = i;

     for (int i = 2; i < N; i++)
     {
          if (mind[i] != i)
               continue;
          for (int j = 2 * i; j < N; j += i)
               mind[j] = min(mind[j], i);
     }
}

void divide(int x)
{
     while (x > 1)
     {
          if (v.empty() || v.back() != mind[x])
               v.push_back(mind[x]);
          x /= mind[x];
     }
}

int main()
{
     ios::sync_with_stdio(false);
     cin.tie(0), cout.tie(0);
     init();
     int T;
     cin >> T;
     while (T--)
     {
          int n, m;
          cin >> n >> m;
          if (__gcd(n, m) != 1)
          {
               cout << 0 << endl;
          }
          else
          {
               if (abs(m - n) == 1)
               {
                    cout << -1 << endl;
               }
               else
               {
                    int x = abs(m - n);
                    divide(x);
                    int ans = 0x3f3f3f3f;
                    int tem;
                    for (int i = 0; i < v.size(); i++)
                    {
                         tem = (int)ceil(n * 1.0 / v[i]);
                         ans = min(ans, tem * v[i] - n);
                    }
                    cout << ans << endl;
                    v.clear();
               }
          }
     }
     return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值