编程题解2025-1
1、将整数换成分数
[题目描述]
一个小于100万的正整数n,尝试把n变成带分数形式,也就是 n=a+b/c,其 中a,b,c是三个正整数,并且数字1~9(不含0)在a、b、c中,必须出现,且只能出现一次。例如:100=3+69258/714,其中1到9这9个数字全都出现了,并且只出现一次。当然,100还等于82+3546/197,也就是说将100变成带分数形式,会有两种组合方式。事实上100,可以写成11种1到9组成整数加上分数的形式。
请编写一个程序,根据一个输入N,程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的全部可能性。不要求输出每个表示,只输出有多少种表示法!
KIMI:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
// 检查一个数字是否由1到9组成,且不重复
bool isValid(const vector<int>& digits) {
vector<bool> used(10, false);
for (int digit : digits) {
if (digit == 0 || used[digit]) {
return false;
}
used[digit] = true;
}
return true;
}
// 计算带分数表示的数量
int countFractionalRepresentations(int n) {
int count = 0;
vector<int> digits = {1, 2, 3, 4, 5, 6, 7, 8, 9};
do {
// 尝试所有可能的a值
for (int a = 1; a < 10; ++a) {
// 剩余的数字
vector<int> remaining;
for (int digit : digits) {
if (digit != a) {
remaining.push_back(digit);
}
}
// 尝试所有可能的b和c的组合
do {
int b = remaining[0] * 1000 + remaining[1] * 100 + remaining[2] * 10 + remaining[3];
int c = remaining[4] * 100 + remaining[5] * 10 + remaining[6];
if (c != 0 && a + b * 1.0 / c == n) {
count++;
}
} while (next_permutation(remaining.begin(), remaining.end()));
}
} while (next_permutation(digits.begin(), digits.end()));
return count;
}
int main() {
int n;
cout << "请输入一个正整数(小于100万):";
cin >> n;
if (n <= 0 || n >= 1000000) {
cout << "输入的数字不符合要求!" << endl;
return 1;
}
int result = countFractionalRepresentations(n);
cout << "数字 " << n << " 有 " << result << " 种带分数表示方法。" << endl;
return 0;
}
代码解释
isValid 函数:检查一个数字是否由1到9组成,且不重复。虽然在这个程序中没有直接使用,但可以用于验证输入的合法性。
countFractionalRepresentations 函数:使用 next_permutation 生成所有可能的数字组合。
尝试所有可能的 a 值(1到9)。
对于每个 a,生成剩余的数字组合,尝试所有可能的 b 和 c 的组合。
检查 a+ b/c是否等于 n,如果是,则计数。
主函数:
从用户输入一个正整数 n。调用 countFractionalRepresentations 函数计算带分数表示的数量。输出结果。
综合:
#include<bits/stdc++.h>
using namespace std;
// 判断三个整数的组合是否包含1到9且每个数字只出现一次
bool isValidCombination(int a, int b, int c) {
string str = to_string(a) + to_string(b) + to_string(c);
if (str.size() != 9) return false; // 长度必须正好为9
unordered_set<char> digits(str.begin(), str.end());
return digits.size() == 9 && digits.find('0') == digits.end(); // 不包含0且包含所有数字1-9
}
int main() {
int n;
cin >> n;
int count = 0;
// 枚举所有可能的a
for (int a = 1; a < n; ++a) {
// 枚举所有可能的c,c最多4位,最大值为9876
for (int c = 1; c <= 9876; ++c) {
// 计算 b 的值
long long b = (long long)(n - a) * c;
if (b > 0 && b < 9876543) { // 确保b是正整数且不会超出范围
// 检查a, b, c的数字组合是否符合要求
if (isValidCombination(a, b, c)) {
count++;
}
}
}
}
cout << count << endl;
return 0;
}
2、

要解释这段代码,我们可以从功能、语法细节、逻辑流程三个方面展开:
一、功能概述
这段代码的作用是:判断输入的字符串是否满足 “奇数位是小写字母,偶数位是大写字母” 的规则。其中,字符串的索引从 0 开始(0 是第 1 位,视为偶数位;1 是第 2 位,视为奇数位,以此类推)。
二、语法与库说明
#include <bits/stdc++.h>:包含 C++ 所有常用标准库(是竞赛类代码的简化写法)。
#include <cctype>:提供字符判断函数(如 islower 判断小写、isupper 判断大写)。
#include <vector>:虽然此处未直接使用,但属于标准库头文件。
using namespace std;:使用标准命名空间,简化代码书写。
using LL = long long;:将 long long 类型别名定义为 LL(此处未使用,属于通用代码习惯)。
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);:关闭输入输出同步,加速 cin/cout 的读取速度(竞赛中常用优化)。
三、逻辑流程
输入测试用例数 t:循环处理 t 个字符串。
读取字符串 s 并获取长度 n:
Lambda 表达式 ok 实现规则判断:
&:定义一个捕获所有外部变量(如 n、s)的匿名函数(Lambda)。
循环遍历字符串每个字符的索引 i:
条件 ((i & 1) && islower(s[i])):i & 1 为真表示 i 是奇数(二进制最后一位为 1),此时需判断 s[i] 是否为小写字母(islower)。
条件 ((~i & 1) && isupper(s[i])):~i 是 i 的按位取反,~i & 1 为真表示 i 是偶数(二进制最后一位为 0),此时需判断 s[i] 是否为大写字母(isupper)。
若上述任一条件不满足,返回 false;全部满足则返回 true。
根据 ok() 的返回值输出结果:若返回 true 输出 "Yes",否则输出 "No"。
示例理解
若输入字符串为 "AbCd":
索引 0(偶数):'A' 是大写 → 满足;
索引 1(奇数):'b' 是小写 → 满足;
索引 2(偶数):'C' 是大写 → 满足;
索引 3(奇数):'d' 是小写 → 满足;
最终输出 "Yes"。
若输入字符串为 "aBc":
索引 0(偶数):'a' 是小写 → 不满足(要求大写);
最终输出 "No"。
综上,这段代码通过 Lambda 表达式和位运算,高效地实现了对字符串 “奇偶位大小写规则” 的验证。

浙公网安备 33010602011771号