C++密码锁 2023年CSP-S认证真题 CCF信息学奥赛C++ 中小学提高组 第二轮真题解析
C++密码锁
博主推荐
- 所有考级比赛学习相关资料合集【推荐收藏】
1、C++专栏
- 电子学会C++一级历年真题解析
- 电子学会C++二级历年真题解析
- 蓝桥杯C++选拔赛真题解析
- 信息素养大赛C++算法编程挑战赛
2、Python专栏
- 蓝桥杯python选拔赛真题详解
- 蓝桥杯python省赛真题详解
- 蓝桥杯python国赛真题详解
- 信息素养大赛python编程挑战赛
- python等级一级真题解析【电子学会】
- python等级二级真题解析【电子学会】
- python等级三级真题解析【电子学会】
一、题目要求
1、编程实现
小 Y 有一把五个拨圈的密码锁。如图所示,每个拨圈上是从 0 到 9 的数字。每个拨圈都是从 0 到 9 的循环,即 9 拨动一个位置后可以变成 0 或 8,
因为校园里比较安全,小 Y 采用的锁车方式是:从正确密码开始,随机转动密码锁仅一次;每次都是以某个幅度仅转动一个拨圈或者同时转动两个相邻的拨圈。
当小 Y 选择同时转动两个相邻拨圈时,两个拨圈转动的幅度相同,即小 Y 可以将密码锁从 00115 转成 11115,但不会转成 12115。
时间久了,小 Y 也担心这么锁车的安全性,所以小 Y 记下了自己锁车后密码锁的 n 个状态,注意这 n 个状态都不是正确密码。
为了检验这么锁车的安全性,小 Y 有多少种可能的正确密码,使得每个正确密码都能够按照他所采用的锁车方式产生锁车后密码锁的全部 n 个状态。
2、输入输出
输入描述:
输入的第一行包含一个正整数 n,表示锁车后密码锁的状态数。
接下来 n 行每行包含五个整数,表示一个密码锁的状态。
输出描述:输出一行包含一个整数,表示密码锁的这 n 个状态按照给定的锁车方式能对应多少种正确密码。
输入样例:
1
0 0 1 1 5
输出样例:
81
样例说明:
一共有 81 种可能的方案。
其中转动一个拨圈的方案有 45 种,转动两个拨圈的方案有 36 种。
二、算法分析
- 从给定题目的初步分析可以看出,本题要求的是密码锁的正确方案数
- 策略:其实实现的方式有很多种,最简单的可以使用枚举算法,也可以使用逆向思维排除法,数学组合容次原理,多模式字符串匹配等也就是常说的AC自动机
- 这里采用模拟+差分数组的方式进行实现,因为数据量不是很大就5个密码,最大也就是10的5次方;然后对差分数组的值进行判断,差分数组的值不相同的时候,说明拨动的位置不同,统计个数加1;
- 同时如果统计个数超过2个,说明拨动了2个以上的密码,不符合;如果个数等于2的时候要判断拨动的两个密码是不是相邻的,同样不符合
#include "bits/stdc++.h"
using namespace std;
const int N = 10;
int n, a[N][N], res = 0;
int b[N], c[N]; //b数组密码锁每个位置上对应的数字,c数组是差分数组,每个位置上密码锁和给定值的差值
bool check() {for(int i=1; i<=n; i++) {for(int j=1; j<=5; j++) {c[j] = (b[j]-a[i][j]+10) % 10;}if(c[1]==0 && c[2]==0 && c[3]==0 && c[4]==0 && c[5]==0) return false; // 两个密码相等int cnt = 0; // 两个密码对应位置不相等的个数for(int j=1; j<=5; j++) {if(c[j] == 0) continue;cnt++;if(cnt >= 3) return false; // 大于等于3,转一次肯定无法得到a[i],因此直接返回falseif(cnt == 2) {if(c[j-1] != c[j]) return false; // 两个不一样,但是这两个没有相连,也不行,返回false}}}return true;
}int main() {cin >> n;for(int i=1; i<=n; i++) {for(int j=1; j<=5; j++) {cin >> a[i][j];}}for(int i=0; i<10; i++) {b[1] = i;for(int j=0; j<10; j++) {b[2] = j;for(int k=0; k<10; k++) {b[3] = k;for(int l=0; l<10; l++) {b[4] = l;for(int m=0; m<10; m++) {b[5] = m;if(check()) res++;}}}}}cout << res << endl;return 0;
}
本文作者:小兔子编程 作者首页:小兔子编程-CSDN博客
四、运行结果
8
2 3 2 3 2 3 1 27
五、考点分析
难度级别:一般,这题相对而言在于最小花费,具体主要考察如下:
- 分析题目,找到解题思路
- 掌握模拟算法的原理和使用方法
- 学会差分数组的原理和使用
- 能够正确分析出密码锁的拨动符合条件的情况
- 学会数学建模能力以及数学运算与逻辑处理能力
- 学会循环语句的熟练使用和分支语句的的控制处理(for、if)
- 学会调试和校对程序设计与逻辑的完整性
- 学会分析题目,算法分析,将复杂问题模块化,简单化,从中找到相应的解题思路
- 充分掌握数组定义和使用、分支语句、循环语句、差分数组和模拟算法的应用
PS:方式方法有多种,小朋友们只要能够达到题目要求即可!