TheForces Round #43 (DIV2-Forces)

@[TOC](TheForces Round #43 (DIV2-Forces))

点击跳转

A题

在这里插入图片描述
依次类推,不难想题意就是求n中的完全平方数的个数

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while (T--) {
        int n;
        cin>>n;
        int ans=0;
        for(int i=1; i*i<=n; i++) {
            ans++;
        }
        cout<<ans<<'\n';
    }
    return 0;
}

B题

想法不唯一,我的是分个数是奇数,偶数来分别讨论
:前面1到n跳过2,并将2放置末尾
:前面1到n跳过2,4,并将2,4放置末尾

#include <bits/stdc++.h>
using namespace std;
void solve() {
    int n;
    cin>>n;
    if (n<=3) {
        cout<<"-1"<<'\n';
        return;
    }
    if (n % 2 == 0) {
        for(int i=1; i<=n; i++) {
            if (i == 2) continue;
            cout<<i<<" ";
        }
        cout<<"2"<<'\n';
    }else {
        for(int i=1; i<=n; i++) {
            if (i == 2 || i == 4) continue;
            cout<<i<<" ";
        }
        cout<<"2 4"<<'\n';
    }
}
int main() {
    ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while (T--) {
        solve();
    }
    return 0;
}

C1题

需要细心考虑所有情况,很容易漏项,具体看代码中的注释部分

#include<bits/stdc++.h>
using namespace std;
void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    // 计算最大可能的彩色子数组数量
    int max_m;
    if (n == 1) {
        max_m = 1;
    } else if (n == 2) {
        max_m = 3;
    } else {
        max_m = 3 * n - 3;//四个以上必然重复则不满足,于是考虑1,2,3的情况分别为n + (n-1) + (n-2) = 3 * n - 3
    }
    // 检查m是否在有效范围内
    if (m < n || m > max_m) {
        cout << -1 << "\n";
        return;
    }
    // 初始化数组为全1
    vector<int> a(n, 1);
    int need = m - n; // 需要额外增加的数量

    if (need == 0) {
        // 无需额外增加,直接输出全1数组
        for (int num : a) {
            cout << num << " ";
        }
        cout << "\n";
        return;
    }

    // 逐步修改数组元素以增加彩色子数组数量
    for (int i = 1; i < n; ++i) {
        if (need == 0) {
            // 已满足需求,剩余元素与前一个相同
            a[i] = a[i-1];
            continue;
        }
        int max_add;
        if (i == 1) {
            max_add = 1; // 第二个元素最多增加1个
        } else {
            if (a[i-1] != a[i-2]) {
                max_add = 2; // 前两个不同时,最多增加2个
            } else {
                max_add = 1; // 前两个相同时,最多增加1个
            }
        }
        int add = min(need, max_add);
        if (add == 1) {// 增量为1的情况
            if (i == 1) {
                // 与第一个元素不同(1→2)
                a[i] = 2;
            } else {
                if (a[i-1] == a[i-2]) {
                    // 前两个相同,选一个不同的值
                    for (int c = 1; c <= 3; ++c) {
                        if (c != a[i-1]) {
                            a[i] = c;
                            break;
                        }
                    }
                } else {
                    // 前两个不同,选与a[i-2]相同的值(与a[i-1]不同)
                    a[i] = a[i-2];
                }
            }
        } else if (add == 2) {// 增量为2的情况
            // 选与前两个元素都不同的值
            for (int c = 1; c <= 3; ++c) {
                if (c != a[i-1] && c != a[i-2]) {
                    a[i] = c;
                    break;
                }
            }
        }
        need -= add;
    }
    for (int num : a) {
        cout << num << " ";
    }
    cout << "\n";
}

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

D题

重要的在于知道要求欧拉函数值,即【1,b - 1】和b互质的个数
核心分析最简分数的条件转化:
1.对于分数 frac{a}{b} ,需满足:a>0,b>1 gcd(a,b)=1 l <= a+b <= r
2.关键观察:设s = a+b,则a = s-b。此时条件转化为:b的范围:2 <= b <=s-1(因为b>1且a>0,gcd(s-b, b) = 1,而gcd(s-b, b) = gcd(s, b),因此需gcd(s, b) = 1
3.欧拉函数的应用:欧拉函数表示[1, s-1]中与s互质的数的数量。对于每个s,符合条件的b的数量为value_of_ola(s) - 1(减去b=1的情况,因为b>1)。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
long long presum[N];  // 前缀和数组
int value_of_ola[N];  // 欧拉函数值
bool is_prime[N];     // 标记质数
vector<int> primes;   // 存储质数

// 预处理欧拉函数、贡献值和前缀和
void init() {
    // 初始化质数标记
    memset(is_prime, true, sizeof(is_prime));
    is_prime[0] = is_prime[1] = false;
    value_of_ola[1] = 1;  // 1的欧拉函数值为1
    // 线性筛计算欧拉函数,解题重点
    for (int i = 2; i <= 1e6; ++i) {
        if (is_prime[i]) {
            primes.push_back(i);
            value_of_ola[i] = i - 1;  // 质数的欧拉函数值为自身减1
        }
        for (int p : primes) {
            if (1LL *i*p > N) break;
            is_prime[i * p] = false;
            if (i % p == 0) {
                value_of_ola[i * p] = value_of_ola[i] * p;  // i是p的倍数时的欧拉函数计算
                break;
            } else {
                value_of_ola[i * p] = value_of_ola[i] * (p - 1);  // i不是p的倍数时的欧拉函数计算
            }
        }
    }

    // 计算前缀和
    presum[0] = 0;
    for (int s = 1; s <= N; ++s) {
        if (s < 3) {
            presum[s] = 0;  // s<3时无有效分数
        } else {
            presum[s] = presum[s - 1] + (value_of_ola[s] - 1);  // 注意这里,减去b==1的情况,因为b>1,分母大于1.
        }
    }
}

int main() {
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    init();
    int T;
    cin >> T;
    while (T--) {
        int l, r;
        cin >> l >> r;
        cout << presum[r] - presum[l - 1] << '\n';
    }
    return 0;
}

    

还有些题作者还没a出来

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值