题目链接

# 前言

这道题我考场上 17:2017: 20 才调出来,下来一问发现都是暴力枚举写的……

# 分析

# n=1n=1

密码锁共有 55 位,考虑其中一位,
将其转动到任意数字(0099,共 1010 个数字)。
在不与转动前的数字相同的情况下,
共有 99 种可能,那么 55 位密码锁共有 4545 种可能。

再考虑同时转动两个相邻拨圈,一共有 44 种转动的组合,即 (1,2)(1,2)(2,3)(2,3)(3,4)(3,4)(4,5)(4,5)
考虑其中一种组合,将这两个拨圈向一个方向转动。
在不与转动前的数字相同的情况下,可以转 99 次(转 1010 次就又转回来了),
那么 44 种组合共有 3636 种可能。

由上可知,n=1n=1 时,可能的正确密码有且只有 8181 种。

# 对于所有 nn

我们可以枚举这 nn 个密码锁的状态所对应的 8181 种可能的正确密码,
找出同时出现在枚举出的 nn 组正确密码中的密码,也就是让这 nn 组正确密码取交集。
同时出现的密码的数量,也就是交集中密码的数量,即是最终的答案。

# 代码

#include <bits/stdc++.h>
using namespace std;
namespace Main {
	const int N = 8, M = 121;
	int c, ni[N + 1][5 + 1];
	int n[5 + 1], m[M + 1][5 + 1], cnt;
	int mi[N + 1][M + 1][5 + 1], cnti[N + 1];
	int main ( ) {
		cin >> c;
		for ( int i = 1; i <= c; ++ i ) {
			for ( int j = 1; j <= 5; ++ j ) {
				cin >> ni[ i ][ j ];
			}
		}
		if ( c == 1 )  {
			cout << "81\n";
			return 0;
		}
		for ( int cl = 1; cl <= c; ++ cl ) {
			for ( int i = 1; i <= 5; ++ i ) {
				n[ i ] = ni[ cl ][ i ];
			}
			cnt = 0;
			for ( int i = 1; i <= 5; ++ i ) {
				for ( int j = 0; j <= 9; ++ j ) {
					if ( j != n[ i ] ) {
						++ cnt;
						for ( int k = 1; k <= 5; ++ k ) {
							m[ cnt ][ k ] = n[ k ];
						}
						m[ cnt ][ i ] = j;
					}
					if ( i != 5 && j != 9 ) {
						++ cnt;
						for ( int k = 1; k <= 5; ++ k ) {
							m[ cnt ][ k ] = n[ k ];
						}
						m[ cnt ][ i ] = ( n[ i ] + j + 1 ) % 10;
						m[ cnt ][ i + 1 ] = ( n[ i + 1 ] + j + 1 ) % 10;
					}
				}
			}
			if ( cl == 1 ) {
				cnti[ 1 ] = cnt;
				for ( int k = 1; k <= cnt; ++ k ) {
					for ( int a = 1; a <= 5; ++ a ) {
						mi[ 1 ][ k ][ a ] = m[ k ][ a ];
					}
				}
				continue;
			}
			for ( int k = 1; k <= cnt; ++ k ) {
				bool same = false;
				for ( int a = 1; a <= cnti[ cl - 1 ]; ++ a ) {
					bool samei = true;
					for ( int b = 1; b <= 5; ++ b ) {
						if ( m[ k ][ b ] != mi[ cl - 1 ][ a ][ b ] ) {
							samei = false;
							break;
						}
					}
					if ( samei == true ) {
						same = true;
						break;
					}
				}
				if ( same ) {
					++ cnti[ cl ];
					for ( int a = 1; a <= 5; ++ a ) {
						mi[ cl ][ cnti[ cl ] ][ a ] = m[ k ][ a ];
					}
				}
			}
		}
		cout << cnti[ c ] << '\n';
		return 0;
	}
}
int main ( ) {
	ios::sync_with_stdio ( false );
	cin.tie ( nullptr );
	cout.tie ( nullptr );
	// freopen ( "lock.in", "r", stdin );
	// freopen ( "lock.out", "w", stdout );
	return Main::main ( );
}

AC 记录

此文章已被阅读次数:正在加载...更新于