梦熊联盟:202505基础语法-题解

202505基础语法-题解

T1 - 九的倍数

解法
对于 9 的倍数,只需要判定其各位的数码和是否为 9 的倍数即可。
例如判断一个数是不是 9 的倍数,只要判断其各位数字之和是不是 9 的倍数,因为一个数能被 9 整除当且仅当它的各位数字之和能被 9 整除。
因此将输入的数当作字符串读入,把每一位的数码和相加,判断是否为 9 的倍数即可。

Code

#include 
using namespace std;
long long ans;
int main() {
    int t;
    cin >> t;
    while (t--) {
        string s;
        cin >> s;
        int ans = 0;
        for (int i = 0; i < s.length(); i++)
            ans += s[i] - '0';
        if (ans % 9)
            cout << "No\n";
        else
            cout << "Yes\n";
    }
return 0;
}

T2 - 直线

解法
容易发现两个点的斜率为某特定值时,当且仅当它们的横纵坐标相加的值相同。
因为(此处应有公式推导,但原始题解未给出),所以可以利用这一性质解题。
利用桶计算每个横纵坐标之和的值出现了多少次,由于值域范围较大,可以利用map等 STL 工具进行优化,时间复杂度为 O (n)。

Code

#include 
#include 
#include 
#include 
using namespace std;
char a[5005];
int n;
int main() {
    scanf("%s", a + 1);
    n = strlen(a + 1);
    string s;
    int l = 1, r = n, t = 0;
    while (l <= r) {
        if (a[l] < a[r]) {
            cout << a[l];
            l++;
        } else {
            if (a[l] > a[r]) {
                cout << a[r];
                r--;
            } else {
                int ll = l, rr = r;
                while (ll <= rr && a[ll] == a[rr]) {
                    ll++;
                    rr--;
                }
                if (a[ll] <= a[rr]) {
                    cout << a[l];
                    l++;
                } else {
                    cout << a[r];
                    r--;
                }
            }
        }
    }
return 0;
}

T3 - 最小的串

解法
我们很容易想出一个贪心思路,就是每次从头和尾中取较小的字符。但问题来了,如何处理头尾相等的情况呢?
可以选择不断往里找,直到找到两个不相同的位置,比较这两个数,取小的那一边的头或尾即可。时间复杂度为 O (n²),如果实现得更精细可以做到 O (n)。

Code

#include 
#include 
#include 
#include 
using namespace std;
char a[5005];
int n;
int main() {
    scanf("%s", a + 1);
    n = strlen(a + 1);
    string s;
    int l = 1, r = n, t = 0;
    while (l <= r) {
        if (a[l] < a[r]) {
            cout << a[l];
            l++;
        } else {
            if (a[l] > a[r]) {
                cout << a[r];
                r--;
            } else {
                int ll = l, rr = r;
                while (ll <= rr && a[ll] == a[rr]) {
                    ll++;
                    rr--;
                }
                if (a[ll] <= a[rr]) {
                    cout << a[l];
                    l++;
                } else {
                    cout << a[r];
                    r--;
                }
            }
        }
    }
return 0;
}

T4 - 砝码

解法
如何用最少的砝码表示出尽量多的重量?
从二进制的角度,砝码重量一定是形如 2⁰, 2¹, 2², ... 以此类推。
从这个角度,为了能表示出 1 到 n 中的所有重量,最终答案前若干个砝码一定形如 2⁰, 2¹, ..., 2^k,之后的每个数都在某个范围内(例如样例中的数值可以表示成特定组合)。
我们可以枚举 k 的大小,那么剩下所有的数最大的值最小可以是某个值,注意 k 的取值范围且答案为某个表达式,因为(此处应有公式推导,但原始题解未给出),所以单次复杂度为 O (log n)。

Code

#include 
using namespace std;
typedef long long int64;
void work() {
    long long n, m;
    cin >> n >> m;
    long long ans = 1e18;
    for (int i = 0; i <= 30; i++) {
        if (i + 1 > m)
            continue;
        long long D = (1ll << i);
        long long C = (1ll << (i + 1)) - 1;
        if (C >= n) {
            ans = min(ans, D);
            continue;
        }
        long long E = m - (i + 1);
        if (E == 0)
            continue;
        long long F = (n - C) / E + ((n - C) % E > 0);
        if (F > C)
            continue;
        ans = min(ans, max(F, D));
    }
    if (ans == 1e18)
        cout << "-1\n";
    else
        cout << ans << '\n';}
int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    int T;
    std::cin >> T;
    for (; T--;)
        work();
return 0;
}

练习:

https://our.oj.fmcraft.top/contest.php?cid=1003

你可能感兴趣的:(算法,c++,开发语言)