问题描述
以下是我无法解决的面试问题,需要一些帮助。
问题:
一个人正在玩纸,在他的游戏过程中,他将纸垂直折叠一圈,然后水平折叠另一圈,并重复该过程 n 次。完成后,他垂直和水平地切割纸张。手头的任务是将数字“N”作为输入,并按照上述模式将其折叠 n 次后,将其垂直和水平切割后将出现在那里的纸片数。
Constraints:
1< N <10^5
N : Total number of turns
As the answer can be very large output the result mod 10^9+7
测试用例
Input: 0
Output: 4
Input: 1
Output: 6
Input: 2
Output: 9
Input: 3
Output: 15
我试图找到一些数字模式,但找不到任何也这个问题似乎与任何算法无关,因此我无法找到任何合适的方法。请帮忙建议一些方法。
解决方法
正如评论中提到的,您应该在部分(4 个角)而不是在总部分中寻找模式。 我们将像这样枚举角点作为向量:
(a(左上),b(右上),c(左下),d(右下))
同样为了一致性和理解起见,我们总是在垂直折叠中从右向左折叠(右半在左半上)和在水平折叠中从下到上(下半在上半上)我们从水平折叠开始,作为我们将预成型的第一个折叠。
首先我们从每个角的 1 开始,所以当我们除以我们得到所有角的总和时,如下所示:
(1,1,1) = 1 + 1 + 1 + 1 = 4 (n = 0)
让我们看看几次运行后每个角落会发生什么:
(2,2,1) = 2 + 1 + 2 + 1 = 6 (n = 1)
(4,1) = 4 + 2 + 2 + 1 = 9 (n = 2)
(6,3,4,2) = 6 + 3 + 4 + 2 = 15 (n = 3)
(9,6,4) = 9 + 6 + 6 + 4 = 25 (n = 4)
也许一开始很难看出两者之间的关系,但实际上模式非常简单:
(a,b,c,d) -> (a+b,a,c+d,c) 当你垂直折叠时(从右到左)
和
(a,d) -> (a+c,b+d,b) 水平折叠时(从下到上)
所以你可以得到递归关系,这里有一些简单的 C 代码:
int func(int a,int b,int c,int d,int n) {
if (n == 0) return (a + b + c + d);
if (n % 2 == 0) return func(a + b,c + d,n - 1);
else return func(a + c,b + d,n - 1);
}
从这里你可以获得更好的计算结果,但这是一个开始