/// .-~~~~~~~~~-._ _.-~~~~~~~~~-.
/// __.' ~. .~ `.__
/// .'// \./ \\`.
/// .'// | \\`.
/// .'// .-~"""""""~~~~-._ | _,-~~~~"""""""~-. \\`.
/// .'//.-" `-. | .-' "-.\\`.
/// .'//______.============-.. \ | / ..-============.______\\`.
/// .'______________________________\|/______________________________`.
Problem Description
约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下、由小到大顺序串着由64个圆盘构成的塔。目的是将最左边杆上的盘全部移到右边的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面。
现在我们改变游戏的玩法,不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到下盘的上面。
Daisy已经做过原来的汉诺塔问题和汉诺塔II,但碰到这个问题时,她想了很久都不能解决,现在请你帮助她。现在有N个圆盘,她至少多少次移动才能把这些圆盘从最左边移到最右边?
Input
包含多组数据,每次输入一个N值(1<=N=35)。
Output
对于每组数据,输出移动最小的次数。
Sample Input
1
3
12
Sample Output
2
26
531440
题解:
假设将n层塔从A经B移动到C需要 f[n] 步,那么n层汉诺塔的移动顺序可以怎么看:
先将前n-1层从A经B移动到C需要 f[n-1] 步,然后将第n层从A移动到B需要 1 步,再将前n-1层从C经B移动到A,接着讲第n层从B移动到C需要 1 步,最后再将前n-1层从A经B移动到C。
总共需要 3*f[n-1]+2 步。
所以我们可以得到:f[n] = 3 * f[n-1] + 2;
AC代码:
#include<iostream>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
int n;
int main()
{
ll f[40];
f[0] = 0; f[1] = 2;
for (int i = 2; i <= 35; i++)
{
f[i] = 3 * f[i - 1] + 2;
}
while (~scanf("%d",&n))
{
printf("%d\n",f[n]);
}
return 0;
}
Problem Description
In how many ways can you tile a 3xn rectangle with 2x1 dominoes? Here is a sample tiling of a 3x12 rectangle.
Input
Input consists of several test cases followed by a line containing -1. Each test case is a line containing an integer 0 ≤ n ≤ 30.
Output
For each test case, output one integer number giving the number of possible tilings.
Sample Input
2
8
12
-1
Sample Output
3
153
2131
题解:
首先我们可以很容易得到的就,只有当列数为偶数时,才可以摆放。
我们记
f
[
n
]
f[n]
f[n]表示n列的摆放方案数;
我们可以先将n列拆为2,n-2列,2列有3种方法摆放,n-2列有
f
[
n
−
2
]
f[n-2]
f[n−2]种摆放方式,
共
3
∗
f
[
n
−
2
]
3*f[n-2]
3∗f[n−2]种;还可以拆为4,n-4 ; 6,n-6 ;8,n-8……n-2,2列;
每种都有
2
∗
f
[
n
−
i
]
(
i
=
4
,
6
,
8
,
…
…
)
2*f[n-i](i=4,6,8,……)
2∗f[n−i](i=4,6,8,……)种。
将4,6,8……看成一个整体,每个都有正反两种方法。
这样我们就可以简单的写出递推式:
f
(
n
)
=
3
∗
f
(
n
−
2
)
+
2
∗
f
(
n
−
4
)
+
.
.
.
.
.
+
2
∗
f
(
2
)
f(n) = 3*f(n-2)+2*f(n-4)+.....+2*f(2)
f(n)=3∗f(n−2)+2∗f(n−4)+.....+2∗f(2)
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
int n;
int dp[35];
int main()
{
memset(dp,0,sizeof(dp));
dp[0]=1;dp[2]=3;
for(int i=4;i<=30;i++)
{
if(i%2==0)
{
int temp=i;
dp[i]+=3*dp[temp-2];
temp-=2;
while(temp!=0)
{
temp-=2;
dp[i]+=2*dp[temp];
}
}
}
while(scanf("%d",&n))
{
if(n==-1) break;
printf("%d\n",dp[n]);
}
return 0;
}
Problem Description
After the king’s speech , everyone is encouraged. But the war is not over. The king needs to give orders from time to time. But sometimes he can not speak things well. So in his order there are some ones like this: “Let the group-p-p three come to me”. As you can see letter ‘p’ repeats for 3 times. Poor king!
Now , it is war time , because of the spies from enemies , sometimes it is pretty hard for the general to tell which orders come from the king. But fortunately the general know how the king speaks: the king never repeats a letter for more than 3 times continually .And only this kind of order is legal. For example , the order: “Let the group-p-p-p three come to me” can never come from the king. While the order:" Let the group-p three come to me" is a legal statement.
The general wants to know how many legal orders that has the length of n
To make it simple , only lower case English Letters can appear in king’s order , and please output the answer modulo 1000000007
We regard two strings are the same if and only if each charactor is the same place of these two strings are the same.
Input
The first line contains a number T(T≤10)——The number of the testcases.
For each testcase, the first line and the only line contains a positive number n(n≤2000).
Output
For each testcase, print a single number as the answer.
Sample Input
2
2
4
Sample Output
676
456950
Hint
All the order that has length 2 are legal. So the answer is 26*26.
For the order that has length 4. The illegal order are : “aaaa” , “bbbb”………“zzzz” 26 orders in total. So the answer for n == 4 is 26^4-26 = 456950
题意:
求长度为n的序列中,每个字符(a~z)连续出现不超过3次的种数。
题解:
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示长度为i的序列中,以一个字符为结尾,连续出现次数为j的种数;
f
[
i
]
[
0
]
f[i][0]
f[i][0]表示长度为i的序列,每个字符连续出现不超过3次的种数;
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int mod=1e9+7;
int t,n;
ll f[2100][4];
int main()
{
f[1][0]=26;
f[1][1]=26;f[1][2]=0;f[1][3]=0;
f[2][0]=676;f[2][1]=650;f[2][2]=26;
for(int i=3;i<2100;i++)
{
f[i][1]=(f[i-1][1]*25+f[i-1][2]*25+f[i-1][3]*25)%mod;
f[i][2]=f[i-1][1];
f[i][3]=f[i-1][2];
f[i][0]=(f[i][1]+f[i][2]+f[i][3])%mod;
}
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
printf("%lld\n",f[n][0]);
}
return 0;
}