密码锁

我见过的最水的S组题目

这题 n8n\le8,而一共就 10510^5 种密码,考虑暴力枚举。

先枚举可能的密码:

for(int a=0;a<=9;a++)
	for(int b=0;b<=9;b++)
		for(int c=0;c<=9;c++)
			for(int d=0;d<=9;d++)
				for(int e=0;e<=9;e++)
					if(check(a,b,c,d,e)) ans++;

虽然看起来会TLE,但每一位上只有 1010 种可能,一共只有 10×10×10×10×10=10510\times10\times10\times10\times10=10^5 个密码。

接着写 check 函数。

首先,假设密码全是往上划(下划可以看做上划),我们可以统计出实际上每种密码距离第 ii 个每一位要划多少

即定义 ci,j=si,jsdic_{i,j}=s_{i,j}\to sd_i,其中 sdsd 为密码,si,js_{i,j} 为输入数据,aba\to b 表示 aa 向上划多少次为 bb。这里定义成了 chas 函数,代码如下:

int chas(int a,int b)//a向上动多少到达b
{
	if(b>=a) return b-a;
	else return b+10-a;
}

如果 ci,jc_{i,j} 只有一个不为 00,即只划了一次,那么对于这个 sis_i 是满足条件的

如果 ci,jc_{i,j}0,3,4,50,3,4,5 个不为 0000 代表没动),都不符合题意,可直接返回错误。

如果有两个不为 00,则看他们是否相邻、都不为 00、相等。

check 函数代码:

bool check(int a,int b,int c,int d,int e)
{
	int sd[6]={0,a,b,c,d,e};
	for(int i=1;i<=n;i++)
		for(int j=1;j<=5;j++)
			cs[i][j]=chas(s[i][j],sd[j]);
	for(int i=1;i<=n;i++)
	{
		int cha=0;
		for(int j=1;j<=5;j++) if(cs[i][j]) cha++;
		if(cha==1) continue;//只动了一个
		if(cha!=2) return 0;//动了不止两个,肯定不是
		int f=0;
		for(int j=1;j<5;j++)
			if(cs[i][j]==cs[i][j+1]&&cs[i][j]!=0&&cs[i][j+1]!=0)
				{f=1;break;}//达到要求 
		if(!f) return 0;
	}
	return 1;
}

完整代码就不贴了。时间复杂度 O(105×5×n)O(n)O(10^5\times5\times n)\approx O(n)

posted @ 2023-10-22 08:08  sLMxf  阅读(16)  评论(0)    收藏  举报  来源