HDU 1877 又一版 A+B 及 itoa函数 应用 头文件 #include <stdlib.h>

本文介绍了itoa函数的使用方法,包括其参数含义、返回值解释以及注意事项。此外,还提供了itoa函数在C语言中的应用实例,并对比了itoa与sprintf函数的不同之处。
char *itoaint value, char *string,int radix);
原型说明:
value 欲转换的数据。
string:目标字符串的地址。
radix:转换后的进制数,可以是10进制、16进制等。

编辑本段功 能

把一个整数转换为字符串

用 法

itoa(i, num,10);
i ----需要转换成字符串的数字
num---- 转换后保存字符串的 变量
10---- 转换数字的基数(即进制)。10就是说按10进制转换数字。还可以是2,8,16等等你喜欢的进制类型
返回值:指向 num这个字符串的 指针

注意事项:

itoa()函数有3个参数:第一个参数是要转换的数字,第二个参数是要写入转换结果的目标字符串,第三个参数是转移数字时所用的基数(进制)。在上例中,转换基数为10,就意味着以10为转换进制。10:十进制;2:二进制...
itoa并不是一个标准的C函数,它是Windows特有的,如果要写跨平台的程序,请用sprintf。
是Windows平台下扩展的,标准库中有sprintf,功能比这个更强,用法跟printf类似:
char str[255];
sprintf(str, "%x", 100); //将100转为16进制表示的字符串。
下列函数可以将整数转换为字符串:

编辑本段数字转化为字符串函数名 及 功能

itoa() 将整型值转换为字符串
l itoa() 将 长整型值转换为字符串
ultoa() 将无符号 长整型值转换为字符串

AC代码:
#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
char s[100];
int main(){
	int m,a,b;
	while(cin>>m,m){
		cin>>a>>b;
		memset(s,0,sizeof(s));
		itoa(a+b,s,m);
		cout<<s<<endl;
	}
	return 0;
}


你提供的 C 代码实现了个数位 DP 的框架,目的是求区间 `[l, r]` 内不含 `4` 和 `62` 的数字个数(类似 HDU 2089 “不要62”)。但这段代码存在 **多个严重错误**,会导致运行结果错误或未定义行为。 我们来逐层分析问题,并给出修正本。 --- ## ❌ 主要问题汇总 | 问题 | 类型 | 影响 | |------|------|------| | 1. `solve()` 中调用 `dfs(digit[k-1], ...)` 错误 | 逻辑错误 | 传入了错误的 `pos` 值 | | 2. `a[]` 数组未赋值 | 运行时错误 | `limit` 判断失效 | | 3. `mem[pos] = temp;` 不该在所有情况下都缓存 | 逻辑错误 | 缓存污染,导致结果错误 | | 4. `dfs(pos == -1)` 返回 0 而不是 1 | 逻辑错误 | 所有路径都被算作“无效” | | 5. `pre == 6 && i == 2` 时跳过,但初始 `pre=-1` 安全吗? | 边界问题 | 需处理边界 | | 6. 多组测试中没有重置 `mem` 数组 per query | 性能/正确性问题 | 只应在每轮 solve 前清空次 | --- ## ✅ 详细分析每个问题 ### 🔴 问题 1:`solve()` 函数中调用 `dfs(digit[k-1], ...)` 是错的! ```c return dfs(digit[k - 1], -1, true); ``` ❌ 错! ✅ 正确应该是:`dfs(k - 1, -1, true)` 因为: - `pos` 表示当前处理的位置索引(从高位到低位) - `k` 是总位数,最高位是 `k-1` - 应该从 `pos = k - 1` 开始递归 你现在传的是 `digit[k-1]`,也就是最高位上的数字(比如 123 的 `digit[2]=1`),这被当成了 `pos`,显然不对! --- ### 🔴 问题 2:`a[]` 数组没有赋值 你在 `dfs` 中用了: ```c int up = limit ? a[pos] : 9; ``` 但是整个程序中 **从未将 `digit[]` 赋给 `a[]`**! 所以 `a[]` 全是随机值(未初始化),导致 `up` 错误! ✅ 必须在 `solve()` 中复制: ```c for (int i = 0; i < k; i++) { a[i] = digit[i]; } ``` > 注意:`digit[]` 是低位在前(逆序存储),正好适合数位 DP 使用。 --- ### 🔴 问题 3:`mem[pos] = temp;` 在所有情况下都写入缓存 ```c if (!limit && mem[pos] != -1) return mem[pos]; ... mem[pos] = temp; ``` ❌ 错!你即使在 `limit == true` 时也写了 `mem[pos] = temp;`,这是致命错误! 👉 含义:把依赖具体上界的“受限路径”结果缓存下来 → 下次遇到不同数字也会复用 → 结果错误! ✅ 正确做法:**只有 `!limit` 时才缓存** ```c if (!limit) mem[pos] = temp; ``` --- ### 🔴 问题 4:`pos == -1` 返回 0 ```c if (pos == -1) return 0; ``` ❌ 错!这意味着:“个完整的数字构造完成”,但它返回 0,表示不合法。 但实际上我们应该统计这样的合法路径。 ✅ 正确应返回 1:表示成功构造了个合法数字。 ```c if (pos == -1) return 1; ``` --- ### 🔴 问题 5:`pre == 6 && i == 2` 判断中 `pre=-1` 是否安全? 初始调用:`dfs(k-1, -1, true)` 第层循环时 `pre = -1`,不会触发 `pre == 6`,所以是安全的。 ✅ 这个没问题,可以接受。 但建议改为 `pre` 为 `-1` 表示“无前位”,逻辑清晰。 --- ### 🔴 问题 6:`mem` 数组只在最外层 `t--` 循环前清空次? 看主函数: ```c while (t--) { scanf("%lld %lld", &l, &r); memset(mem, -1, sizeof(mem)); // ✅ 每次查询前都清空,OK printf("%lld\n", solve(r) - solve(l - 1)); } ``` ✅ 这部分是对的!每次 `solve(x)` 前都会重新初始化 `mem`,避免跨查询污染。 但如果 `solve(l-1)` 和 `solve(r)` 共享缓存?不行!它们面对不同的 `x`,必须分开计算。 所以你必须在每次 `solve(x)` 之前 **重新提取 `a[]` 并清空 `mem`** —— 当前结构勉强可行,但仍需修复其他问题。 --- ## ✅ 修复后的完整正确代码(已修正所有问题) ```c #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <stdbool.h> #define N 20 int a[N]; // 存储每位数字(低位在前) long long mem[N]; // 记忆化数组 int digit[N]; // 临时存储分解后的数字 long long dfs(int pos, int pre, bool limit); long long solve(long long x); int main() { int t; while (scanf("%d", &t) == 1) { while (t--) { long long l, r; scanf("%lld %lld", &l, &r); memset(mem, -1, sizeof(mem)); long long ans_r = solve(r); memset(mem, -1, sizeof(mem)); // 重新清空 long long ans_l_minus = solve(l - 1); printf("%lld\n", ans_r - ans_l_minus); } } return 0; } // 数位 DP:统计不含 4 和 62 的数字个数 long long dfs(int pos, int pre, bool limit) { if (pos == -1) { return 1; // 成功构造个合法数字 } // 只有不受限时才能使用缓存 if (!limit && mem[pos] != -1) { return mem[pos]; } int up = limit ? a[pos] : 9; long long temp = 0; for (int i = 0; i <= up; i++) { if (i == 4) continue; // 禁止 4 if (pre == 6 && i == 2) continue; // 禁止 62 temp += dfs(pos - 1, i, limit && (i == a[pos])); } // 只有不受限时才缓存 if (!limit) { mem[pos] = temp; } return temp; } // 分解数字并启动 DFS long long solve(long long x) { if (x < 0) return 0; // 处理 l=1 时 l-1=0 的情况 int k = 0; while (x > 0) { digit[k++] = x % 10; x /= 10; } // 将 digit 复制到 a[] for (int i = 0; i < k; i++) { a[i] = digit[i]; } // 从最高位开始搜索 return dfs(k - 1, -1, true); } ``` --- ## ✅ 改进说明总结 | 修改点 | 说明 | |--------|------| | `dfs(k-1, ...)` | 传位置索引而非数字值 | | `a[i] = digit[i]` | 正确设置数位数组 | | `mem[pos] = temp` 加条件 | 仅当 `!limit` 时缓存 | | `pos==-1` 返回 1 | 表示合法路径 | | 每次 `solve` 前清空 `mem` | 避免缓存污染 | | `solve(-1)` 特判 | 若 `l=0` 可进步优化,此处假设 `l>=1` | --- ## ✅ 测试样例验证 输入: ``` 1 1 20 ``` 合法数字(不含 4 和 62): - 排除含 4 的:4, 14, 24... → 本范围内:4, 14 - 排除 62:不在范围内 - 所以总数 = 20 - 2 = 18?不对! 实际检查: 1~20 中排除: - 4 → 排除 - 14 → 排除 → 共排除 2 个 → 合法:18 个 输出应为 `18` 你的原始代码会输出什么?很可能是 `0` 或负数,因为 `dfs(...)` 返回 0。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值