牛客周赛 Round 98 [A-F]

小红很喜欢奇数。现在小红得到了一个正整数 x。小芳能帮他进行恰好一次如下操作:

操作:使得 x 加上自己的一个因子。

小红想知道小芳能不能帮他把 x 变成奇数,请你帮帮他。

//因为数据量不大,可以直接暴力。
void solve() {
    int n;
    cin >> n;
    int ans = n;
    for(int i = 1; i <= n; i++){
        if(n % i == 0 && (ans + i) % 2 != 0){
            cout << "Yes" << endl;
            return;
        }
    }
    cout << "No" << endl;
}
//当然仔细想一想,它是要相加得到奇数,那么可以知道 偶数 + 1(1一定是一个因子)= 奇数
void solve() {
    cin >> n;
    if (n % 2 != 0)
        cout << "No" << endl;
    else
        cout << "Yes" << endl;
}

小红很喜欢 gcd 和 三角形。现在小红得到了两个正整数 x 和 y,请你帮她判断以 xy 和 gcd(x, y) 这三个整数作为边长,能否组成一个非退化的三角形

//莫得好说的
void solve() {
    int x,y;
    cin >> x >> y;
    int ans = __gcd(x,y);
    if(x + y > ans && x + ans > y && y + ans > x){
        cout << "Yes" << endl;
    }else{
        cout << "No" << endl;
    }
}

小红很喜欢 red
现在小红拿到了一个长度为 n 的仅由 'r''e''d' 组成的字符串。小芳可以帮她进行任意次如下操作:

  • 操作:将字符串的任意一位修改为 'r''e''d' 中的一个字符。

小红不希望字符串中存在任何相邻且相同的字符,请你用尽可能少的操作次数修改字符串使其符合要求。

//看题意,就知道肯定得相邻的不同,而且才变化三个字母,可以直接扫过去
void solve() {
    int n;
    cin >> n;
    string s;
    cin >> s;
    vector<char> chars = {'r', 'e', 'd'};
    for (int i = 1; i < s.size(); i++) {
        if (s[i] == s[i-1]) {
            for (char c : chars) {
                if (c != s[i-1] && (i+1 >= s.size() || c != s[i+1])) {
                    s[i] = c;
                    break;
                }
            }
        }
    }

    cout << s <<endl;
}

题目描述

小红很喜欢 好数组
定义一个数组是「好数组」当且仅当满足以下条件:

  1. 相邻元素不同(即数组中任意两个相邻的数不相等);
  2. 所有元素均为正整数

现在输入一个正整数 n,你需要找到所有满足以下条件的数组:

  • 数组的所有元素之和等于 n
  • 数组是「好数组」。

并按 字典序从小到大 的顺序依次输出所有满足条件的数组。

set<vector<int>> ans_set;
//第一感觉,肯定是用dfs去构造 sum = n的数组,然后全排列,判断能不能符合条件
void dfs(int target, vector<int> path, int start) {
    //cout << target << " ";
    if (target == 0) {
        //cout << endl;
        vector<int> ans_vec = path;
        sort(ans_vec.begin(), ans_vec.end());
        do {
            bool flag = true;
            for (int i = 0; i < ans_vec.size() - 1; i++) {
                if (ans_vec[i] == ans_vec[i + 1]) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                ans_set.insert(ans_vec);
            }
        } while (next_permutation(ans_vec.begin(), ans_vec.end()));
        return;
    }
    for (int i = start; i <= target; i++) {
        path.push_back(i);
        dfs(target - i, path, i);
        path.pop_back();
    }
}

void solve() {
    int n;
    cin >> n;
    vector<int> path;
    dfs(n, path, 1);
    for (auto arr : ans_set) {
        for (int num : arr) {
            cout << num << " ";
        }
        cout << endl;
    }
}
//后面想了一下,发现不需要去全排列
vector<int> ans_set;
void dfs(int sum, int n) {
    if(sum == n){
        for(auto num : ans_set){
            cout << num << " ";
        }
        cout << endl;
        return;
    }
    for (int i = 1; i <= n; i++) {
        if(sum + i <= n && (ans_set.empty() || ans_set.back() != i)){
             ans_set.push_back(i);
            dfs(sum + i, n);
            ans_set.pop_back();
        }
    }
}

void solve() {
    int n;
    cin >> n;
    dfs(0,n);
}

小红很喜欢 gcd 和 sum
小红定义一个长度为 k 的数组 {a₁, a₂, ..., aₖ} 的权值为:

权值 = gcd(a₁, a₂, ..., aₖ) × (a₁ + a₂ + ... + aₖ)

其中:

  • gcd(a₁, a₂, ..., aₖ) 表示这些数的最大公约数
  • (a₁ + a₂ + ... + aₖ) 表示这些数的和

现在给定一个长度为 n 的数组 {a₁, a₂, ..., aₙ},小红可以从中选择一个非空子序列。请找到所有可能的非空子序列中权值最大的那个,并输出这个最大权值。

//一个想法是,我们把所有数字的因数都保存下来
//比如1或者2,是 2 6 4 的因数
//比如3,是 6 的因数
//比如4,是 4 的因数
//....
void solve() {
    int n;
    cin >> n;
    vector<int> arr(n);
    for(int i = 0; i < n; i++){
        cin >> arr[i];
    }

    unordered_map<int, vector<int>> unorderedMap;
    set<int> uniqueSet;

    for(auto num : arr){
        vector<int> tempVec;
        //cout << "num = " << num <<endl;
        for(int i = 1; i * i <= num; i++){
            if(num % i == 0){
                tempVec.push_back(i);
                uniqueSet.insert(i);
                if(num / i != i){
                    tempVec.push_back(num / i);
                    uniqueSet.insert(num / i);
                }
            }
        }
        for(auto d : tempVec){
            //cout << d << " ";
            unorderedMap[d].push_back(num);
        }

        //cout << endl;
    }

    // for(auto d : unorderedMap){
    //     cout << d.first << endl;
    //     for(auto c : d.second){
    //         cout << c << "->";
    //     }
    //     cout << endl;
    // }
  

    LL result = 0;
    //然后我们枚举这些因数,得到哪些数字是共同存在这个因数的,把他们按照公式算一下求最大值
    for(auto it = uniqueSet.rbegin(); it != uniqueSet.rend(); it++){
        int d = *it;
        auto nums = unorderedMap[d];
        if(nums.empty()) continue;

        int cur = nums[0];
        LL sum = 0;
        for(auto num : nums){
            cur = __gcd(cur, num);
            sum += num;
        }
        if(cur == d){
            result = max(result, d * sum);
        }
    }

    cout << result << endl;
}
// 实际上没那么复杂,要想得到最大值,肯定得是 2 4 6 8 或者是 12 24 36 这种拥有倍数关系的数字,很容易看出来最大公约数是2和12
// 如果不是倍数,极大可能最大公约数是1这种
oid solve()
{
    int n;
    std::cin >> n;
    std::vector<int> cnt(N);
    for (int i = 1; i <= n; i++) {
        int x;
        std::cin >> x;
        cnt[x]++;
    }
 
    i64 ans = -1;
    for (i64 i = 1; i < N; i++) {
        i64 s = 0;
        for (i64 j = i; j < N; j += i) {
            s += j * cnt[j]; // ,后面算求和
        }
        ans = std::max(ans, i * s);//i为最大公约数
    }
    std::cout << ans << "\n";
}

小红很喜欢天使猫猫酱。
今天天使猫猫酱的题目过于简单,小红觉得不够过瘾,于是想出了一个更难的版本:

问题定义

有两个无限长的整数数组 a 和 b

  1. 数组 a 的定义如下:

    • 第 i 项 aᵢ = 22^m,其中 m 是由 i 个数字 '2' 连续拼接而成的十进制数
    • 举例:
      • a₁ = 22^2 
      • a₂ = 22^22
      • a₃ = 22^222
      • ...(依此类推)
  2. 数组 b 的定义:

    • 第 i 项 bᵢ = aᵢ 的正因子个数(包括 1 和 aᵢ 本身)。

问题要求

给定一个正整数 n,求数组 b 的前 n 项之和:

由于结果可能非常大,输出 S mod 998244353

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll MOD = 998244353;

ll power(ll base, ll exp) {
    ll res = 1;
    base %= MOD;
    while (exp > 0) {
        if (exp & 1) res = res * base % MOD;
        base = base * base % MOD;
        exp >>= 1;
    }
    return res;
}

ll modinv(ll x) {
    return power(x, MOD - 2);
}

ll sum(ll r, ll n) {
    if (r == 1) return n % MOD;
    ll numerator = (power(r, n + 1) - r + MOD) % MOD;
    ll denominator = modinv(r - 1);
    return numerator * denominator % MOD;
}
//这个数学推算比较复杂,建议直接看结论
//或者分段,先去就22^2....2的因数个数公式,然后再得到求和公式,最后简化
int main() {
    ll n;
    cin >> n;

    cout << ((4 * sum(100, n) + 28 * sum(10, n) + 49 * (n % MOD)) % MOD * modinv(81) % MOD) << endl;
    return 0;
}

 

posted @ 2025-06-30 00:34  樱花落舞  阅读(30)  评论(0)    收藏  举报