前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >程序员进阶之算法练习(一百)

程序员进阶之算法练习(一百)

作者头像
落影
发布2024-03-09 07:57:52
720
发布2024-03-09 07:57:52
举报
文章被收录于专栏:落影的专栏落影的专栏

新年伊始,终到百篇,龙年大吉。

题目1

题目链接 题目大意: 给出一个整数,问该整数能否切分为两个数字a和b,满足: 1、a和b都不包括前导零,是一个正常的数字; 2、a和b都大于0; 3、b > a;

如果可以,则输出数字a和b;如果不可以则输出-1;

输入: 第一行,整数𝑡 表示t个样例 𝑡 (1≤𝑡≤10000) 每个样例一行,单个整数 (数字长度为2~8)

输出: 每个样例一行,如果可以,则输出数字a和b;如果不可以则输出-1;

Examples input 5 20002001 391125 200200 2001000 12

output 2000 2001 39 1125 -1 200 1000 1 2

题目解析: 按照题目的要求,a要尽可能小,b要尽可能大。 由于题目给出的数字本身就合法,那么将第一个数字开始分为a,往后找到第一个非零的数字就分给b,这样b一定是最大的。 从字符串上切分好a和b,接下来就是转成数字。 这里为了便于计算,从字符串a右边开始往左边枚举每一个位置上的数字,就可以得到数字a。(数字b同理,也可以字符串切割后,用sscanf取巧)

代码语言:javascript
复制
class Solution {
    static const int N = 201010;
public:
    void solve() {
        int t;
        cin >> t;
        while (t--) {
            string str;
            cin >> str;
            int k = 1, n = str.length();
            while (k < n) {
                if (str[k] != '0') break;
                ++k;
            }
            if (k >= n) {
                cout << -1 << endl;
                continue;;
            }
            int x = 0, y = 0;
            int tmp = k - 1, val = 1;
            while (tmp >= 0) {
                x += val * (str[tmp] - '0');
                --tmp;
                val *= 10;
            }
            tmp = n - 1, val = 1;
            while (tmp >= k) {
                y += val * (str[tmp] - '0');
                --tmp;
                val *= 10;
            }
            if (x < y) cout << x << " " << y << endl;
            else  cout << -1 << endl;
        }
    }
}
ac;

题目2

题目链接 题目大意: 给出一个01字符组成的字符串𝑠,现在可以对字符串进行任意次下面操作: 1、删除字符串中的某个一个字符,代价为1; 2、调换两个位置上的字符,代价为0;

现在要求,若干次操作后的字符串t,t上面每一个字符都与原来字符串s的字符相反,比如说: s=011 那么t=10,最小操作代价是1,移除一个字符1,然后交换一次0、1的位置;

s=111100 那么t=00,最小操作代价是4,移除所有字符1;

问生成满足要求的字符串t,最小的代价是多少。(注意移除所有字符也满足要求)

输入: 第一行,整数𝑡 表示t个样例 𝑡 (1≤𝑡≤10000) 每个样例一行,字符串𝑠 (1≤ |𝑠| ≤2⋅1e5)

输出: 每个样例一行,输出满足题目要求的最小代价;

Examples input 4 0 011 0101110001 111100

output 1 1 0 4

题目解析: 按照题目的要求,直接看最终字符串t的样式,比如说s=111100,那么t=001111; 那么只需要累计原来0、1的数字数量,然后从左到右枚举t的位置,直到剩下的字符无法填充,那么就得到t的最大长度; 得到t的最大长度k,那么需要移除的字符串长度就是n--k。

代码语言:javascript
复制
class Solution {
    static const int N = 201010;
public:
    void solve() {
        int t;
        cin >> t;
        while (t--) {
            string str;
            cin >> str;
            int n = str.length(), x = 0, y = 0;
            for (int i = 0; i < n; ++i)
                if (str[i] == '0') ++x;
                else ++y;
            int k = 0, cntX = x, cntY = y;
            while (k < n) {
                if (str[k] == '0') {
                    if (y > 0) --y;
                    else break;
                }
                else {
                    if (x > 0) --x;
                    else break;
                }
                ++k;
            }
            if (x + y == 0) {
                cout << 0 << endl;
            }
            else {
                cout << n - k << endl;
            }
        }
    }
}
ac;

题目3

题目链接 题目大意: 给出一个空的数组,现在有两个操作: 操作1,往数组添加一个数字2^x; 操作2,询问数组中的若干个数字,数字和是否可以为w;

输入: 第一行,整数𝑡 表示m个操作 (1≤m≤100000) 每个操作一行 操作1,是输入1和x (0≤x≤29 ). 操作2,是输入2和w;(0≤w≤1e9 ).

输出: 每个操作2输出一行,存在则输出YES,不存在输出NO;

Examples input 5 1 0 1 0 1 0 2 3 2 4

output YES NO

题目解析: 题目的数据范围简化了题目,首先x比较小,数组中最多只有30个整数类型,那么可以按照这个规则聚类; 其次,在判断数组是否存在某个元素和时,可以从大到小遍历数组,对于某个元素y如果小于等于当前w,则优先取用,并且w=w-y,直到数组末尾;如果此时w=0,则有解,否则无解;

代码语言:javascript
复制
class Solution {
   static const int M = 536870912; // 2^29
   int a[30];
public:
   void solve() {
       int t;
       cin >> t;
       while (t--) {
           int k, x;
           cin >> k >> x;
           if (k == 1) a[x]++;
           else {
               int cur = M;
               for (int i = 29; i >= 0; --i) {
                   if (a[i] > 0 && x >= cur) {
                       int left = 1, right = a[i] + 1;
                       int find = left;
                       while (left < right) {
                           int mid = (left + right) / 2;
                           lld sum = 1LL * mid * cur;
                           if (sum > x) {
                               right = mid;
                           }
                           else {
                               find = mid;
                               left = mid + 1;
                           }
                       }
                       x -= find * cur;
                   }
                   cur /= 2;
               }
               cout << (x == 0 ? "YES" : "NO") << endl;
           }
           
       }
   }
}
ac;

题目4

题目链接 题目大意: 有两个整数n和k,n表示字符串长度,k表示字符串由前k个小写字符; 现在需要构造一个字符串s,要求任何长度为n的字符串,都是字符串s的子序列;

输入: 第一行,整数𝑡 表示t个样例 𝑡 (1≤𝑡≤676) 每个样例一行,整数n和k (1≤𝑛≤26 ) and (1≤𝑘≤26 ).

输出: 每个样例一行,输出字符串s,如果有多个则输出最短长度的字符串;

Examples input 4 1 2 2 1 2 2 2 3

output ab aa baab abcbac

题目解析: 题目的要求,所有常读为n的字符串,在拼接的时候就可以看成是n个选择,每次从k个字符中选择一个; 那么在构造的时候,可以采用这样的策略: 我们重复abc/abc/abc这样的字符串,每一组都相当有k个不同字符的桶。 这样构造出来的结果就能满足要求。

代码语言:javascript
复制
class Solution {
    static const int N = 201010;
public:
    void solve() {
        int t;
        cin >> t;
        while (t--) {
            int n, k;
            cin >> n >> k;
            for (int i = 0; i < n; ++i) {
                for (int j = 0; j < k; ++j) putchar('a' + j);
            }
            cout << endl;
        }
    }
}
ac;

题目5

题目链接 题目大意: 有一个正整数x,现在需要把x分成n个正整数,这些正整数之和是x; 现在要求,n个正整数的最大公约数,尽可能的大;

输入: 第一行,整数𝑡 表示t个样例 𝑡 (1≤𝑡≤1000) 每个样例一行,整数𝑥和 𝑛 (1≤𝑥≤1e8) and (1≤𝑛≤𝑥).

输出: 每个样例一行,输出最大的公约数。

Examples input 3 10 3 5 5 420 69

output 2 1 6

题目解析: 按照题目的要求,全部拆分成数字1,必然可以拆出满足要求: k-1个整数1,剩下的整数是x-n-1,这些整数的最大公约数是1;

同理,假如最大公约数是2,可以这么拆: k-1个整数2,剩下的整数是x-2n-2,最大的公约数是2;

也就是说,假设最大公约数是k,也可以这么安排:n-1个整数k,剩下是x-kn-k;

由于题目的范围不大,那么枚举最大公约数的数字就好。

代码语言:javascript
复制
class Solution {
  static const int N = 201010;
public:
  void solve() {
      int t;
      cin >> t;
      while (t--) {
          int x, n;
          cin >> x >> n;
          int k = sqrt(x) + 1;
          int ans = 1;
          for (int i = 1; i <= k; ++i) {
              if (x % i == 0) {
                  if (i >= n) ans = max(ans, x / i);
                  if (x / i >= n) ans = max(ans, i);
              }
          }
          cout << ans << endl;
      }
  }
}
ac;
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目1
  • 题目2
  • 题目3
  • 题目4
  • 题目5
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档