Chinese Rings (九连环+矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2842

题目:

Problem Description

Dumbear likes to play the Chinese Rings (Baguenaudier). It’s a game played with nine rings on a bar. The rules of this game are very simple: At first, the nine rings are all on the bar.
The first ring can be taken off or taken on with one step.
If the first k rings are all off and the (k + 1)th ring is on, then the (k + 2)th ring can be taken off or taken on with one step. (0 ≤ k ≤ 7)

Now consider a game with N (N ≤ 1,000,000,000) rings on a bar, Dumbear wants to make all the rings off the bar with least steps. But Dumbear is very dumb, so he wants you to help him.

Input

Each line of the input file contains a number N indicates the number of the rings on the bar. The last line of the input file contains a number "0".

Output

For each line, output an integer S indicates the least steps. For the integers may be very large, output S mod 200907.

Sample Input

1
4
0

Sample Output

1
10

题意:给你个n连环(就是平时玩的九连环类的益智玩具,还不知道的就请自行百度一下啦……),问最少要操作多少次才能把所有的环取下来~

思路:个人认为这是要靠经验来,没玩过的可能不知道该怎样取才能把所有的环都取下来。第n项与前几项的关系是f(n)=f(n-1)+2*f(n-2) + 1,解释一下这个递推公式就是你要取下第n个的话得先把1~n-2都取下来(第一个f(n-2)),第n-1个挂在上面,然后把第n个取下来(递推公式中1的由来),然后再把1~n-2全部挂上去(第二个f(n-2)),然后就是把第n-1取下去(f(n-1))。因为就可以构造出矩阵了,f[0] = 2, f[1] = 1, f[2] = 1;
        a[0][0] = 1, a[0][1] = 1, a[0][2] = 0;
        a[1][0] = 2, a[1][1] = 0, a[1][2] = 0;
        a[2][0] = 1, a[2][1] = 0, a[2][2] = 1。

代码实现如下:

 1 #include <cstdio>
 2 #include <cstring>
 3
 4 typedef long long ll;
 5 const int mod = 200907;
 6 int n;
 7 int f[3], a[3][3];
 8
 9 void mul(int f[3], int a[3][3]) {
10     int c[3];
11     memset(c, 0, sizeof(c));
12     for(int i = 0; i < 3; i++) {
13         for(int j = 0; j < 3; j++) {
14             c[i] = (c[i] + (ll) f[j] * a[j][i]) % mod;
15         }
16     }
17     memcpy(f, c, sizeof(c));
18 }
19
20 void mulself(int a[3][3]) {
21     int c[3][3];
22     memset(c, 0, sizeof(c));
23     for(int i = 0; i < 3; i++) {
24         for(int j = 0; j < 3; j++) {
25             for(int k = 0; k < 3; k++) {
26                 c[i][j] = (c[i][j] + (ll) a[i][k] * a[k][j]) % mod;
27             }
28         }
29     }
30     memcpy(a, c, sizeof(c));
31 }
32
33 int main() {
34     while(~scanf("%d", &n) && n) {
35         if(n == 1) {
36             printf("1\n");
37             continue;
38         }
39         if(n == 2) {
40             printf("2\n");
41             continue;
42         }
43         f[0] = 2, f[1] = 1, f[2] = 1;
44         a[0][0] = 1, a[0][1] = 1, a[0][2] = 0;
45         a[1][0] = 2, a[1][1] = 0, a[1][2] = 0;
46         a[2][0] = 1, a[2][1] = 0, a[2][2] = 1;
47         n = n - 2;
48         for(; n; n >>= 1) {
49             if(n & 1) mul(f, a);
50             mulself(a);
51         }
52         printf("%d\n", f[0] % mod);
53     }
54     return 0;
55 }

原文地址:https://www.cnblogs.com/Dillonh/p/8972145.html

时间: 2024-10-21 20:04:30

Chinese Rings (九连环+矩阵快速幂)的相关文章

HDU 2842 Chinese Rings (带常数矩阵+矩阵快速幂)

HDU 2842 Chinese Rings (带常数矩阵+矩阵快速幂) ACM 题目地址:HDU 2842 Chinese Rings 题意: 一种中国环,解开第k个环需要先解开前(k-2)个环,并留有第(k-1)环.问解开n环最少需要几步. 分析: 设f(n)表示解开n环. 1. 由于游戏规则,解开n环不能一下子把n-1全解开了,否则第n个就没法拿掉了. 2. 得先拿掉第n个:先完成f(n-2),然后再拿掉第n环. 3. 然后放回前(n-2),其实这也是f(n-2),因为是一个逆的过程. 4

HDU 2842 Chinese Rings(矩阵快速幂+递推)

题目地址:HDU 2842 这个游戏是一个九连环的游戏. 假设当前要卸下前n个环.由于要满足前n-2个都卸下,所以要先把前n-2个卸下,需要f(n-2)次.然后把第n个卸下需要1次,然后这时候要卸下第n-1个,然后此时前n-2个都已经被卸下了.这时候把前n-2个都卸下与都装上所需的次数是一样的,因为卸下与装上的规则是一样的.所以又需要f(n-2)次,这时候前n-1个都在上面,卸下前n-1个需要f(n-1)次. 所以,总共需要2*f(n-2)+f(n-1)+1次. 然后构造如下矩阵. 1,2,1

HDU2842-Chinese Rings(递推+矩阵快速幂)

题目链接 题意:求出最少步骤解出九连环.取出第k个的条件是,k-2个已被取出,k-1个仍在支架上. 思路:想必九连环都玩过吧,其实最少步骤就是从最后一个环开始,向前一直取出来就行了.所以假设取出前n个环所需要的步骤为f(n),那么在此之前f(n - 2)要被取出,再加上1,即第n个环被取出,所以只剩下第n-1环没被取出,那么我们将前n-2环再套上去(套上去和取下来的步骤是一样,都为f(n - 2)),所以取出n-1环的步骤为f(n - 1),因此可以得到一个递推公式:f(n) = f(n - 2

bnu 34985 Elegant String(矩阵快速幂+dp推导公式)

Elegant String Time Limit: 1000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main Prev Submit Status Statistics Discuss Next Type: None None Graph Theory      2-SAT     Articulation/Bridge/Biconnected Component      Cy

矩阵快速幂专题(一)

最近闲来无事,准备集中精力刷一波数论与图论.矩阵快速幂是数论里面的重要组成部分,值得我好好学习一下.因为题目比较多,分析也比较多,所以将此专题分成几个部分.做完这一专题,可能会暂时转向图论部分,然后等我组合数学学得差不多了,再回过头来继续做数论题. 矩阵快速幂算法的核心思想是将问题建模转化为数学模型(有一些简单题目是裸的矩阵模型,但是大部分难题就是难在要构造矩阵,用矩阵方法解决问题),推倒递推式,构造计算矩阵,用快速幂的思想求解矩阵A的n次方取mod,从而得到矩阵里面你需要的数据. 矩阵快速幂问

HDU 5318 The Goddess Of The Moon(矩阵快速幂详解)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5318 题面: The Goddess Of The Moon Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 800    Accepted Submission(s): 349 Problem Description Chang'e (嫦

矩阵快速幂刷题系列

来源自http://blog.csdn.net/chenguolinblog/article/details/10309423 hdu 1575 Tr A Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5587    Accepted Submission(s): 4200 Problem Description A为一个方阵,则Tr

HDU 1757 A Simple Math Problem (矩阵快速幂)

[题目链接]:click here~~ [题目大意]: If x < 10 f(x) = x. If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + -- + a9 * f(x-10); 问f(k)%m的值. [思路]:矩阵快速幂,具体思路看代码吧,注意一些细节. 代码: #include<bits/stdc++.h> using namespace std; typedef long long LL; const

Codeforces Round #291 (Div. 2) E - Darth Vader and Tree (DP+矩阵快速幂)

这题想了好长时间,果断没思路..于是搜了一下题解.一看题解上的"快速幂"这俩字,不对..这仨字..犹如醍醐灌顶啊...因为x的范围是10^9,所以当时想的时候果断把dp递推这一方法抛弃了.我怎么就没想到矩阵快速幂呢.......还是太弱了..sad..100*100*100*log(10^9)的复杂度刚刚好. 于是,想到了矩阵快速幂后,一切就变得简单了.就可以把距离<=x的所有距离的点数都通过DP推出来,然后一个快速幂就解决了. 首先DP递推式很容易想到.递推代码如下: for(