2*~~
include <stdio.h>
include <stdlib.h> //qsort函数
include <stdbool.h>
define max(a, b) ((a) > (b) ? (a) : (b))
define min(a, b) ((a) < (b) ? (a) : (b))//71,72行
typedef struct //定义一个结构体 c=a*b
{
int c; // 乘积
int a; // 较小乘数
int b; // 较大乘数
} Result;
// check函数 检查a、b、c的数字1-9是否各出现一次且无0!!!
bool check(int a, int b, int c)
{
int digits[10] = {0}; // 记录数字出现次数(索引0-9,但只用1~9下标号
// 检查并记录a的每一位
int num = a;
while (num > 0)
{
int d = num % 10;
if (d == 0 || digits[d]++) return false; // 含0或重复,if()里的条件为真就执行return
//digits[d]本来是0(初始化),如果d出现了,digits[d]值=1,如果再出现了,就是复自增
num /= 10;
}
// 检查并记录b的每一位
num = b;
while (num > 0) {
int d = num % 10;
if (d == 0 || digits[d]++) return false; // 含0或重复
num /= 10;
}
// 检查并记录c的每一位
num = c;
while (num > 0) {
int d = num % 10;
if (d == 0 || digits[d]++) return false; // 含0或重复
num /= 10;
}
// 验证1-9各出现一次
for (int i = 1; i <= 9; i++) {
if (digits[i] != 1) return false;
}
return true;
}
// 排序规则:先按c升序,再按a升序
int compare(const void *a, const void b)
{ //(Result )a是强制类型转换:将void类型的a转换为 Result类型
Result *ra = (Result *)a;// Result *raint *ra ; (Result *)a(int *)a强制转换
Result *rb = (Result )b; //ra,rb指向result结构体的不同变量 ;a 是较小乘数,b 大 〤
if (ra->c != rb->c)//先排乘积c
{ //ra->c等价于(ra).c 即访问ra指向的Result结构体的c成员
return ra->c - rb->c;
}
else
{
return ra->a - rb->a;//再排a
}
}
int main() {
Result results[100]; // 存储结果,结构体Result类型
int count = 0; // 结果计数
// 1:2位 × 3位 = 4位
for (int a = 10; a <= 99; a++)
{ // a是2位数,算b的最小值(向上取整:1000/a 的上界)
int min_b = (1000 + a - 1) / a; //见注释(3)
// b的最大值(向下取整:9999/a 的下界)
int max_b = 9999 / a;
// b必须是3位数(100-999)
min_b = max(min_b, 100);
max_b = min(max_b, 999);
/* 等价于
if (min_b < 100)
min_b = 100; // 让min_b至少是100
if (max_b > 999) max_b = 999; // 让max_b至多是999*/
if (min_b > max_b) continue; // 无有效b,跳过
for (int b = min_b; b <= max_b; b++)
{ // b是3位数
int c = a * b;
if (c < 1000 || c > 9999) continue; // c必须是4位数
if (check(a, b, c))
{
results[count].c = c;
results[count].a = a;
results[count].b = b;
count++;
}
}
}
// ---------- 情况2:1位 × 4位 = 4位 ----------
for (int a = 1; a <= 9; a++)
{ // a是1位数
int min_b = 1000; // b必须是4位数(1000-9999)
int max_b = 9999 / a; // c = a*b ≤ 9999 → b ≤ 9999/a
if (max_b < 1000) continue; // 无有效b,跳过
for (int b = min_b; b <= max_b; b++)
{ // b是4位数
int c = a * b;
if (c < 1000 || c > 9999) continue; // c必须是4位数
if (check(a, b, c))
{
results[count].c = c;
results[count].a = a;
results[count].b = b;
count++;
}
}
}
// 按规则排序结果
qsort(results, count, sizeof(Result), compare);
// 首地址 元素个数 元素大小 参考函数
// 输出结果
for (int i = 0; i < count; i++) {
printf("%d = %d x %d\n", results[i].c, results[i].a, results[i].b);
}
return 0;
}
bug:保怎么证每个数只出现一次? check()函数,检查记录a,b,c每一位
结果大小怎么排序?quick sort函数
收获(1)digits[d]++:这是后自增运算(先判断旧值,再+1) 。digits[d] 的初始值是0(数组默认初始化),表示该数字还没出现过。如果digits[d] 旧值为0:判断结果是false(不触发return),然后digits[d]变为1(记录“该数字出现1次”)。如果digits[d] 旧值为1:说明该数字已经出现过一次(重复了),判断结果为true,触发return false。
若digits[d] 已为 1 → 重复(同一数字出现多次
(2)可是你上面给出的代码里好像没有写把每次取余过后的d读入到数组digits[]里面?
代码里的“记录”过程,其实藏在++里虽然代码没有写digits[d] =digits[d] +1,但后自增的副作用已经完成了“记录数字出现次数”的操作:第一次遇到数字d: digits[d] 从0变为1(记录“出现1次”)。第二次遇到数字d:digits[d] 已经是1,直接触发“重复”判断。
(3)最小值 min_b:因为c =axb≥1000,所以b≥1000/a。但整数除法会向下取整(1000/11~90.9,实际 b需≥91才能让c≥1000),因此用向上取整公式:
原理:(分子+分母-1)/分母等价于对分子/分母 向上取整(如(1000+11-1)/11=1010/11=91.81→91)
bug:
收获:好难啊 ┭┮﹏┭┮
浙公网安备 33010602011771号