数学逻辑
一、拆解整数(提取各位数字)
这是最基础的操作。核心口诀:取末位用 % 10,扔掉末位用 / 10。
1. 提取固定位数(比如三位数)
| int n = 248;
int ge = n % 10; // 个位:8
int shi = n / 10 % 10; // 十位:4
int bai = n / 100 % 10; // 百位:2
|
2. 通用提取(利用 while 循环,适合任意位数)
| int n = 12345;
while (n > 0) {
int digit = n % 10; // 拿到当前最低位
cout << digit << " "; // 输出:5 4 3 2 1(倒序输出)
n /= 10; // 扔掉最低位
}
|
二、构造整数(正序与倒序)
这在之前的 248 题里你已经用过了,这是初学者最容易搞混的地方。核心口诀:倒序拼凑用乘法 * 10 +,正序拼凑用权重 * power。
1. 整数倒序(最常用)
| int n = 12345, rev = 0;
while (n > 0) {
rev = rev * 10 + n % 10; // 先出来的个位,不断被推到最高位
n /= 10;
}
// rev 最终为 54321
|
2. 整数正序(配合权重)
| int n = 12345, res = 0, power = 1;
while (n > 0) {
res = res + (n % 10) * power; // 个位乘1,十位乘10...
power *= 10;
n /= 10;
}
// res 最终为 12345
|
3. 字符串拼接法(适合不做数学运算,只做展示)
| string s = to_string(12345);
reverse(s.begin(), s.end()); // 需要包含 <algorithm> 头文件
int rev = stoi(s); // 转回整数
|
三、整数基本属性(位数、求和、回文)
基于前面的逻辑,衍生出的常见题型。
1. 求一个整数是几位数
| int n = 12345, count = 0;
while (n > 0) {
count++;
n /= 10;
}
// count 为 5
|
2. 求各位数字之和
| int n = 12345, sum = 0;
while (n > 0) {
sum += n % 10; // 累加每一位
n /= 10;
}
// sum 为 15
|
3. 判断回文数(正着读和倒着读一样)
| int n = 12321, temp = n, rev = 0;
while (temp > 0) {
rev = rev * 10 + temp % 10;
temp /= 10;
}
if (rev == n) cout << "是回文数"; // 成立
|
四、基础数论(编程题常客)
1. 求最大公约数(辗转相除法 / 欧几里得算法)
| int a = 24, b = 36;
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
// a 最终为 12(最大公约数)
|
2. 求最小公倍数
| // 公式:a * b / 最大公约数
int lcm = 24 * 36 / 12; // 结果为 72
|
_注意:实际写代码时,建议先除后乘,防止溢出:a / gcd _ b。*
3. 判断质数(素数)
| bool isPrime(int n) {
if (n <= 1) return false;
for (int i = 2; i * i <= n; i++) { // i * i 是核心优化
if (n % i == 0) return false;
}
return true;
}
|
4. 冒泡排序
| #include <iostream>
using namespace std;
int main() {
int arr[] = {5, 2, 9, 1, 5, 6};
int n = sizeof(arr) / sizeof(arr[0]); // 自动计算数组长度
// 外层循环:控制比较的轮数,一共需要 n-1 轮
for (int i = 0; i < n - 1; i++) {
// 内层循环:控制每一轮的比较次数
// 每过一轮,就会有一个最大的数被排到末尾,所以比较次数要减去 i
for (int j = 0; j < n - 1 - i; j++) {
// 如果前一个数比后一个数大,就交换它们(升序)
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
// 输出排序后的结果
cout << "排序后:";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
|
五、浮点数与取整(需要 <cmath> 头文件)
C++ 中整数除法 / 是直接截断(丢弃小数),比如 3 / 2 = 1。
| 函数 |
含义 |
示例 |
floor(x) |
向下取整 |
floor(2.9) → 2.0 |
ceil(x) |
向上取整 |
ceil(2.1) → 3.0 |
round(x) |
四舍五入 |
round(2.5) → 3.0 |
(int)x |
强制截断 |
(int)2.9 → 2 |
abs(x) |
绝对值 |
abs(-5) → 5(整数)或 fabs(-5.5)(浮点数) |
⚠️ 初学者大坑:
7 / 2 = 3(整数除法),但 7.0 / 2 = 3.5。
想要得到精确小数,至少要把其中一个操作数写成小数:7.0 / 2 或 (double)7 / 2。
六、通用进制转换(短除法)
这是你之前 248 题用到的核心逻辑。十进制转其他进制(如七进制、九进制、二进制),万能模板:
| int n = 248;
int base = 7; // 目标进制
int res = 0, power = 1; // 如果转成数字
string s = ""; // 如果转成字符串展示
while (n > 0) {
int digit = n % base; // 取余数
res = res + digit * power; // 正序拼凑
power *= 10;
s = char(digit + '0') + s; // 字符串拼接(倒序插入)
n /= base;
}
|
字符逻辑
// 字符串转大写(const 引用 + 返回值)
| string toUpper(const string &s)
{
string result = s;
for (char &c : result)
{
if (c >= 'a' && c <= 'z')
{
c = c - 'a' + 'A';
}
}
return result;
}
|
// 反转字符串
| string reverseString(const string &s)
{
string result;
for (int i = (int)s.size() - 1; i >= 0; i--)
{
result += s[i];
}
return result;
}
|
💡 给初学者的 3 个建议:
- 优先用
while(n > 0) 循环处理整数,这比用 for 循环硬算位数灵活得多。
% 和 / 是黄金搭档,几乎所有整数拆解问题都靠它们。
- 多画图、多手动模拟。遇到卡壳的逻辑,拿一张纸,把
n 和 res 的变化过程一行行写出来,瞬间就能看懂。
把这些模板吃透,以后遇到“水仙花数”、“回文数”、“进制转换”、“数位统计”这类题,你就能直接秒杀了。加油!