记录37
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[11]={},cnt,i;
for(i=192;i<333;i++){
memset(a,0,sizeof(a));
cnt=0; a[i/100]=a[i/10%10]=a[i%10]=a[2*i/100]=a[2*i/10%10]=a[2*i%10]=a[3*i/100]=a[3*i/10%10]=a[3*i%10]=1;
for(int j=1;j<=9;j++) cnt+=a[j];
if(cnt==9) cout<<i<<" "<<i*2<<" "<<i*3<<endl;
}
return 0;
}
题目传送门
https://www.luogu.com.cn/problem/P1008
突破点
将 1,2,…,9 共 9 个数分成 3 组,分别组成 3 个三位数,且使这 3 个三位数构成 1:2:3 的比例,试求出所有满足条件的 3 个三位数。
思路
- 用桶来记录数字的出现情况
- 取出记录的每个数字
- 符合条件就输出
代码简析
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[11]={},cnt,i;
for(i=192;i<333;i++){
memset(a,0,sizeof(a));
cnt=0;
...
...
}
return 0;
}
a[11]数组用来记录1~9出现的数字情况
for(i=192;i<333;i++){} 因为三个数最大也不会超过999,所以i取到333
memset(a,0,sizeof(a)); 数组初始化,在补充部分详细介绍
cnt=0; 每次都要重新记录数字出现的个数
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[11]={},cnt,i;
for(i=192;i<333;i++){
memset(a,0,sizeof(a));
cnt=0; a[i/100]=a[i/10%10]=a[i%10]=a[2*i/100]=a[2*i/10%10]=a[2*i%10]=a[3*i/100]=a[3*i/10%10]=a[3*i%10]=1;
for(int j=1;j<=9;j++) cnt+=a[j];
if(cnt==9) cout<<i<<" "<<i*2<<" "<<i*3<<endl;
}
return 0;
}
a[i/100]=a[i/10%10]=a[i%10]=a[2*i/100]=a[2*i/10%10]=a[2*i%10]=a[3*i/100]=a[3*i/10%10]=a[3*i%10]=1;
对每个数进行取出来,因为是1:2:3的关系,所以直接乘对应的倍数
for(int j=1;j<=9;j++) cnt+=a[j]; 统计出现的桶数字出现的个数
if(cnt==9){} 符合条件就输出
补充
memset函数详解与使用指南
1. 函数原型与头文件
#include <cstring> // C++ 推荐 // 或 #include <string.h> // C风格 void *memset(void *s, int c, size_t n);参数说明:
s:指向要填充的内存块的起始地址
c:要填充的值(0~255,但实际以int类型传递)
n:要填充的字节数
2. 最常用场景:清零操作
int a[100]; memset(a, 0, sizeof(a)); // 将整个数组每个元素置0 // 等价于 for (int i = 0; i < 100; i++) a[i] = 0;优势:代码简洁,执行速度极快(通常由硬件指令优化)。
3. 典型应用场景
场景 代码示例 说明 静态数组清零 int arr[1000]; memset(arr, 0, sizeof(arr));将数组所有元素设为0 动态数组清零 int* p = new int[100]; memset(p, 0, 100 * sizeof(int));注意:sizeof(p)仅指针大小 结构体清零 Student s; memset(&s, 0, sizeof(s));快速初始化所有成员为0/NULL 二维数组清零 int g[100][100]; memset(g, 0, sizeof(g));sizeof(g)自动计算总字节数
4. 按字节填充原理与陷阱
memset按字节填充,这是其强大与危险的根源:
清零(0):任何类型都适用,因为全0字节对数值类型就是0,对指针就是NULL
置-1:
memset(arr, -1, sizeof(arr));也普遍适用,因为-1的补码是0xFF陷阱:不能填充非0xFF的值到多字节类型
int arr[10]; memset(arr, 1, sizeof(arr)); // 危险! // 每个int元素实际是 0x01010101 = 16843009,不是1!
5. 不同类型数据的处理
数值类型:
// ✅ 正确:清零或置-1 memset(arr, 0, sizeof(arr)); memset(arr, -1, sizeof(arr)); // ❌ 错误:意图赋其他值 memset(arr, 1, sizeof(arr)); // 实际得到16843009字符数组:
char str[100]; memset(str, 'A', sizeof(str)); // ✅ 正确:所有字符为'A' // 或填充空字符串 memset(str, 0, sizeof(str)); // 全'\0',等价于空字符串布尔数组:
bool flag[100]; memset(flag, 0, sizeof(flag)); // ✅ 全false memset(flag, 1, sizeof(flag)); // ✅ 全true(所有字节为1)
6. 动态内存的特殊处理
// ❌ 错误示范 int* p = new int[100]; memset(p, 0, sizeof(p)); // 只清零了指针本身(4/8字节) // ✅ 正确写法 memset(p, 0, 100 * sizeof(int)); // 计算总字节数 // 或 int n = 100; int* p = new int[n]; memset(p, 0, n * sizeof(int));
7. 与初始化/赋值的区别
方式 时机 效率 适用场景 int a[100] = {0};编译时 最快 静态数组,只能初始化为0 memset(a, 0, sizeof(a));运行时 极快 任意时刻,可重复清零 fill(a, a+100, 0);运行时 较快 可赋任意值,需头文件 <algorithm>for循环赋值运行时 较慢 灵活,但代码冗余
8. 竞赛高频错误
struct Node { int val; vector<int> adj; }; Node nodes[100]; memset(nodes, 0, sizeof(nodes)); // ❌ 危险! // 仅将val清零,vector内部状态被破坏致命问题:
memset对包含非POD类型(如string,vector)的结构体是未定义行为,会导致程序崩溃。正确做法:
、
for (int i = 0; i < 100; i++) { nodes[i].val = 0; nodes[i].adj.clear(); }
9. 性能与适用性
性能:在-O2优化下,
memset通常比手动循环快数倍适用性:仅适用于POD类型(Plain Old Data),如基本类型、数组、不含复杂成员的struct
不推荐:含
string,vector,map等STL成员的结构体
10. 竞赛最佳实践
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 5; int arr[MAXN]; bool vis[MAXN]; long long dp[MAXN][2]; int main() { // ✅ 标准清零模板 memset(arr, 0, sizeof(arr)); memset(vis, 0, sizeof(vis)); memset(dp, 0, sizeof(dp)); // 对long long同样有效 // ✅ 多组数据测试时的重置 int T; cin >> T; while (T--) { int n; cin >> n; memset(arr, 0, sizeof(int) * (n + 1)); // 只清零前n+1个 // ... 处理逻辑 } // ✅ 结构体初始化(仅含POD成员) struct Edge { int u, v, w; }; Edge edges[MAXN]; memset(edges, 0, sizeof(edges)); return 0; }
核心要点总结
万能公式:
memset(arr, 0, sizeof(arr));永远安全仅限-1:
memset(arr, -1, sizeof(arr));对整数数组有效动态数组:必须手动计算字节数
n * sizeof(type)结构体:仅当所有成员都是POD类型时才可用
速度:竞赛中清零操作应优先使用
memset,比循环快且代码简洁陷阱:绝不用memset赋1或其他非0xFF值,结果不符合预期
掌握以上用法,可确保在CSP竞赛中安全、高效地使用
memset。
446

被折叠的 条评论
为什么被折叠?



