PTA 编程题(C语言)-- 连续因子

题目标题: 连续因子               题目作者 陈越 浙江大学

一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3×5×6×7,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。

输入格式:

输入在一行中给出一个正整数 N(1<N<231)。

输出格式:

首先在第 1 行输出最长连续因子的个数;然后在第 2 行中按 因子1*因子2*……*因子k 的格式输出最小的连续因子序列,其中因子按递增顺序输出,1 不算在内。

输入样例:

630

输出样例:

3
5*6*7

这道题目初看会觉得很难,仔细观察一下还是有思路的。首先对题目中的有关概念做以下解释。

所为连续因子序列是指,按照从小到大的次序排列的一串连续的正整数a、a+1、a+2 ...  a+n-1,若他们的乘机能够整除N,则称这串数是N的一个连续因子序列,其中正整数的个数n,叫做这个连续因子序列的长度。对于一个正整数N的连续因子序列,我们需要知道一下三点事实:

(1)N一定有连续因子序列。例如N本身就是一个长度为1的连续因子序列。

(2)N一定有一个最长连续因子序列。因为N是有限的,故他的连续因子序列不可能 无限长。

(3)N的最长连续因子序列可能不唯一,若N有若干的长度都是最长的连续因子序列,则这个因子序列中起始因子最小的序列,称为最小的连续因子序列。

本题就是要在N的最长因子序列中寻找最小的。

思路:对于一个给定的i,我们用里层循环找到从i开始的最长因子序列;用外层循环让i从2开始遍历到N,如果新找的到的因子序列比之前找到的长,我们用新找到的去更换当前最长续因子序列;由于我们每次找的最长因子序列的起始因子是从2开始递增的,故找到的最长因子序列一定是最小的。

注意:外循环的循环变量i是遍历起始因子的,所以i从2开始遍历。至于i到哪里结束呢?如果N是素数,则我们需要让i能取到N,但是这样会有一个测试点运行超时。如果N不是素数,我们只需要让i取到sqrt(N)即可,这样也不会超时。所以我们的处理办法是,就让i取到sqrt(N),如果没有找到最小因子序列,则说明N一定是素数,就按素数的情况输出即可。

另外,我们用来存放因子序列的数组的长度设置为12就可以了,因为13!将超过给定的正整数N的上限,也就是说对于题目给定的N,它的最长因子序列不可能超过12。

代码1:

#include <stdio.h>
#include <math.h> 
int main () {
    int N, M, i, j, lenS = 0, lenT = 0, S[12] = {0},T[12] = {0};
    scanf("%d", &N);
    for (i = 2; i <= sqrt(N); i++) {
        M = 1;
        for (j = 0; j < 12; j++) {
            M *= (i+j);
            if (N%M == 0) {
                T[j] = i+j;
                lenT = j+1;
            } 
            else break;
        }
        if (lenT > lenS) {  // 如果新找的的连续因子序列T比S长,我们就用T替换S
            for (j = 0; j < lenT; j++) {
                S[j] = T[j];
            }
            lenS = lenT;
        }
    }
    if (lenS == 0) {   // 没有找长度大于1的连续因子序列的情况,说明N是素数。
        printf("1\n%d",N);
    } else {
        printf("%d\n", lenS);
        for (i = 0; i < lenS-1; i++) printf("%d*", S[i]);
        printf("%d",S[i]);  
    }
    return 0;
}

优化:因为要记录一个连续因子,起始只需要记录它的其实因子和长度就可以了,没有必要用数组记录下整个因子序列,基于这个想法我们有如下的优化

代码2:

#include <stdio.h>
#include <math.h> 
int main () {
    int N, M, i, j, lenS = 0, lenT, S = 0, T = 0;
    scanf("%d", &N);
    for (i = 2; i <= sqrt(N); i++) {
        M = 1;
        T = i;
        for (j = 0; j < 12; j++) {
            M *= (i+j);
            if (N%M == 0) {
                lenT = j+1;
            } 
            else break;
        }
        if (lenT > lenS) {
            S = T;
            lenS = lenT;
        }
    }
    if (lenS == 0) {
        printf("1\n%d",N);
    } else {
        printf("%d\n", lenS);
        for (i = 0; i < lenS-1; i++) printf("%d*", S+i);
        printf("%d",S+i);  
    }
    return 0;
}

  更多PTA题目的的参考代码,可以在wx小程序里搜“PTA刷题助手”,或扫下面的二维码

在 C 语言中,假设你需要编写一个程序解决“买 U 盘”的问题,这是一个常见的算法题目,通常涉及输入一组价格和需求量,然后计算最小花费购买满足所有需求的 U 盘。以下是一个简单的示例: ```c #include <stdio.h> // 定义结构体存储每个 U 盘的价格和需求量 typedef struct { int price; int demand; } USB; // 比较函数,用于二分查找找到满足需求的最小价格 int min_price(int u[], int n, int total_demand) { int left = 0; int right = n - 1; while (left <= right) { int mid = left + (right - left) / 2; if (u[mid].price * u[mid].demand >= total_demand) right = mid - 1; // 需求可以在当前价格范围内买到 else left = mid + 1; // 需求大于当前价格范围,向右移动搜索 } return left; // 返回左边界,即最小价格对应的索引 } int main() { int n; printf("请输入 U 盘的价格数组长度:"); scanf("%d", &n); USB u[n]; // 价格和需求量的数组 for (int i = 0; i < n; i++) { printf("请输入第 %d 个U盘的价格和需求量:", i + 1); scanf("%d %d", &u[i].price, &u[i].demand); } int total_demand; printf("请输入总需求量:"); scanf("%d", &total_demand); int min_cost = 0; for (int i = 0; i < n; i++) { min_cost += u[min_price(u, n, total_demand)].price * u[min_price(u, n, total_demand)].demand; total_demand -= u[min_price(u, n, total_demand)].demand; if (total_demand == 0) break; // 如果所有需求都满足,跳出循环 } printf("最小花费为:%d 元\n", min_cost); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值