P9752 [CSP-S 2023] 密码锁题解

1.题意:

从正确密码开始,随机转动密码锁一次,每次可以:

  1. 转动一个拨圈(数字可以增加或减少)

  2. 同时转动两个相邻的拨圈(两个拨圈变化幅度相同)

现在给出了n个锁车后的状态(都不是正确密码),需要计算有多少种可能的正确密码,使得每个正确密码都能通过上述操作产生所有给定的n个状态。

2.思路:

  1. 对于每个可能的正确密码,我们需要验证它是否能通过单次操作(单拨圈或双相邻拨圈转动)生成所有给定的n个状态。

  2. 五位密码共有10^5=100,000种可能,可以全部枚举。

  3. 对于每密码,检查:

    • 对于每个给定的状态,至少存在一种操作(单拨圈或双相邻拨圈转动)能从密码得到该状态

    • 密码不能与任何给定状态相同(题目说明)

  4. 统计满足上述所有条件的密码数量。

3.示例解释

对于样例输入1:

1
0 0 1 1 5

可能的正确密码有81种:

  • 45种通过单拨圈转动得到"00115"(每个位置可以±1,共5个位置×9种变化=45)

  • 36种通过双相邻拨圈转动得到"00115"(4对相邻位置×9种变化=36)

36+45=81

因此输出81。

4.AC代码如下:

#include<bits/stdc++.h>
using namespace std;
int a[10][10];
int p[10];
int main(){
	int n,ans=0;
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=5;j++){
			cin>>a[i][j];
		}
	} 
	for(p[1]=0;p[1]<=9;p[1]++){
		for(p[2]=0;p[2]<=9;p[2]++){
			for(p[3]=0;p[3]<=9;p[3]++){
				for(p[4]=0;p[4]<=9;p[4]++){
					for(p[5]=0;p[5]<=9;p[5]++){
						bool flag=0;
						for(int i=1;i<=n;i++){
							int cnt=0;
							for(int j=1;j<=5;j++){
								if(a[i][j]!=p[j]){
									cnt++;
								}
							} 
							if(cnt>=3 || cnt==0){
								flag=1;
								break;
							}
							if(cnt==1) continue;
							for(int j=1;j<=5;j++){
								if(a[i][j]!=p[j]){
									if(a[i][j+1]==p[j+1]){
										flag=1;
										break;
									}
									if((a[i][j]+10-p[j])%10==(a[i][j+1]+10-p[j+1])%10){
										break;
									}
									else {
										flag=1;
										break;
									}
								}
							}
							if(flag==1) break;
						} 
						if(flag==0) ans++;
					}
				}
			}
		}
	}
	cout<<ans;
	return 0;
}           

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值