There is a room with n
lights which are turned on initially and 4 buttons on the wall. After performing exactly m
unknown operations towards buttons, you need to return how many different kinds of status of the n
lights could be.
Suppose n lights are labeled as number [1, 2, 3 ..., n]
, function of these 4 buttons are given below:
- Flip all the lights.
- Flip lights with even numbers.
- Flip lights with odd numbers.
- Flip lights with
(3k + 1)
numbers,k = 0, 1, 2, ...
Example 1:
Input: n = 1, m = 1.
Output: 2
Explanation: Status can be: [on], [off]
Example 2:
Input: n = 2, m = 1.
Output: 3
Explanation: Status can be: [on, off], [off, on], [off, off]
Example 3:
Input: n = 3, m = 1.
Output: 4
Explanation: Status can be: [off, on, off], [on, off, on], [off, off, off], [off, on, on].
Note: n
and m
both fit in range [0, 1000]
.
解法
首先一看,m和n都有1000那么大,我立马放弃了暴力……虽然好像搜索也可以过……?
首先,很容易注意到:
- 这些操作的作用顺序与结果无关
- 重复2次同一个操作相当于没做操作,所以每个操作只可能有0和1两种状态
- 操作2+操作3=操作1
那么最后的状态只取决于这4个操作的状态,所以总共的自变量最多只有16个,而最终灯的状态可能更少。
首先我们想想,m次操作怎么样实现出这16种状态呢?假如我们想得到0001
(操作1~4分别做0、0、0、1次),我们只需要把一个1分给操作4,然后剩下的m-1随便分成4个偶数【这个偶数包括0】,只要m-1是偶数,肯定能分出来。
我自己枚举的时候把16个都搞出来了……,按官方解答走捷径叭Orz
另外,由于操作2+操作3=操作1
,我们进行主成分提取,总共又可以把自变量空间缩小到以下8个状态:
状态 | 结果 | 条件 |
---|---|---|
0000(=1110) | 全开【B+C】 | 【m偶,m>=0】或【m奇,m>=3】 |
0001(=1111) | 除1,4,7……外开【B+C-A】 | 【m偶,m>=4】或【m奇,m>=1】 |
0010(=1100) | 偶开【B】 | 【m偶,m>=2】或【m奇,m>=1】 |
0100(=1010) | 奇开【C】 | 【m偶,m>=2】或【m奇,m>=1】 |
0011(=1101) | 偶数除4,10……,以及1,7,13……是开着的【(B-A)+(C&A)】 | 【m偶,m>=2】或【m奇,m>=3】 |
0110(=1000) | 全关【 ∅ \emptyset ∅】 | 【m偶,m>=2】或【m奇,m>=1】 |
0101(=1011) | 奇数除1,7,13……,以及4,10,……开【(C-A)+(B&A)】 | 【m偶,m>=2】或【m奇m>=3】 |
0111(=1001) | 1,4,7……开【A】 | 【m偶,m>=2】或【m奇,m>=3】 |
其中,B
代表偶数下标集合,C
代表奇数下标集合,A
代表3x+1
下标集合,中括号【】
里表示状态为开
的下标集合
分析完m对结果的影响之后,我们再分析n对结果的影响。n较小的时候,有的结果表现出来是一样的,这时候状态就不可能是8个了
- 分析易知,当
A
、B
、C
互不相同的时候,8个状态各自不同 A
和B
只有n=0
时相同,A
和C
在n=0,1,2
时都相同
所以根据m和n的不同,可以总结出下面的规律:
class Solution(object):
def flipLights(self, n, m):
"""
:type n: int
:type m: int
:rtype: int
"""
if n==0:
return 0
if m==0:
return 1
if n==1:
return 2
if n==2:
return 3 if m==1 else 4
if m==1:
return 4
if m==2:
return 7
return 8