OJ实验:找新朋友

题目描述

新年快到了,天勤准备搞一个聚会,已经知道现有会员N人,把会员从1到N编号,其中会长的号码是N号,凡是和会长是老朋友的,那么该会员的号码肯定和N有大于1的公约数,否则都是新朋友,现在会长想知道究竟有几个新朋友?请你编程序帮会长计算出来。

输入

第一行是测试数据的组数CN(Case number,1<CN<10000),接着有CN行正整数N(1<n<32768),表示会员人数。

输出

对于每一个N,输出一行新朋友的人数,这样共有CN行输出。

样例输入
2
25608
24027

样例输出 复制
7680
16016

 示例:

#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>

using namespace std;

const int MAX_N = 32768;

// 预处理每个数字的因子
vector<vector<int>> preprocess_factors() {
    vector<vector<int>> factors(MAX_N);
    for (int i = 2; i < MAX_N; ++i) {
        for (int j = i; j < MAX_N; j += i) {
            if (i != j) // 排除自身
                factors[j].push_back(i);
        }
    }
    return factors;
}

int main() {
    int CN, N;
    cin >> CN;

    vector<vector<int>> factors = preprocess_factors();

    while (CN--) {
        cin >> N;
        vector<int>& factor_list = factors[N];

        // 使用布尔数组记录是否是老朋友
        vector<bool> is_old_friend(N, false);  // 默认都不是老朋友

        // 标记老朋友
        for (int f : factor_list) {
            for (int k = f; k < N; k += f) {
                is_old_friend[k] = true;
            }
        }

        // 计算新朋友数量
        int new_friends_count = 0;
        for (int i = 1; i < N; i++) {
            if (!is_old_friend[i]) {
                new_friends_count++;
            }
        }

        cout << new_friends_count << endl;
    }

    return 0;
}

预处理函数

vector<vector<int>> preprocess_factors() {
    vector<vector<int>> factors(MAX_N);
    for (int i = 2; i < MAX_N; ++i) {
        for (int j = i; j < MAX_N; j += i) {
            if (i != j) // 排除自身
                factors[j].push_back(i);
        }
    }
    return factors;
}

详细解释

1. 函数声明与返回类型:

vector<vector<int>> preprocess_factors() 

    这是一个函数声明,函数名为`preprocess_factors`,返回类型是`vector<vector<int>>`,即一个二维向量。该函数不接受任何参数。

2. 初始化二维向量:

vector<vector<int>> factors(MAX_N);

    创建一个大小为`MAX_N`(32768)的二维向量`factors`。每个元素都是一个向量,用于存储某个数的因子。例如,`factors[12]`将存储所有12的因子(除了12本身)。

3. 外层循环:

 for (int i = 2; i < MAX_N; ++i) {

    这是一个从2开始,遍历到`MAX_N - 1`的循环。变量`i`表示当前因子。因为1是每个数的因子,但我们不需要考虑1,所以从2开始。

4. 内层循环:
 

    for (int j = i; j < MAX_N; j += i) {

    这是一个内层循环,从`i`开始,以`i`为步长,遍历到`MAX_N - 1`。变量`j`表示当前检查的数字。通过`j += i`,确保`j`是`i`的倍数,也就是说`i`是`j`的因子。

5. 排除自身:
 

    if (i != j) // 排除自身

    检查当前因子`i`是否等于当前数字`j`。如果它们相等(即`i == j`),表示`i`是`j`本身,这时不需要将`i`作为`j`的因子,因为我们只需要存储真正的因子。

6. 添加因子到列表:

    factors[j].push_back(i);

    如果`i`不是`j`,将`i`添加到`j`的因子列表中。这表示`i`是`j`的因子。例如,对于`j = 12`,`i = 3`,3将被添加到`factors[12]`中。

7. 返回结果:

    return factors;

    最后,返回预处理好的因子列表`factors`。`factors`是一个二维向量,其中`factors[i]`存储了所有`i`的因子。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BlueCatの夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值