问题 C: 【递归与递推】九连环
时间限制: 1 Sec 内存限制: 64 MB
题目描述
九连环是由九个彼此套接的圆环和一根横杆组成,九个环从左到右依次为l~9,每个环有两种状 态:1和0,1表示环在杆上,0表示环不在杆上。初始状态是九个环都在杆上,即:111111111,目标状态是九个环都不在杆上,即:000000000,由初始状态到目标状态的变化规则是:
(1)第一环为无论何时均可自由上下横行;
(2)第二只环只有在第一环为1时,才能自由上下;
(3)想要改变第n(n>2)个环的状态,需要先使第一到第(n-2)环均为下杆,且第n-1个环为上杆,而与第n+l个到第九环状态无关;
(4)每改变一个环,记为一步。
现在九连环由111111111变到000000000,求中间第i步的状态。
输入
仅包含一个整数i。
输出
仅包含中间第i步的状态。如果输入的步数大于实际变换所需的步数,则输出-1。
样例输入
【样例1】
2
【样例2】
500
样例输出
【样例1】
010111111
【样例2】
-1
脑子不够。。
题目大意:
给你步数,让你解九连环,看能解到什么状态,其中1实在九连环上,0是不在。
解题思路:
九连环的解法是,要解下第n个,就要n-2及其之前的都必须解下来,n-1在上面,这样才能解下第n个,同时剩下n-1个在上面。特别的,第一个可以自由上下。所以,就是很明显的递归。
递归函数:
参数——ring的编号。
终止条件:步数为0的时候。
递归过程,首先要判断第n-1个是否在上面,如果不在就要让他在上去;
然后遍历n-2之前的是否在上面,如果在,就让他们下来。
note:代码里0是没有解下来,1是已经解下来。
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include <cstdio>
//#define local
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N = 2e4+5;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;
int n;
int ring[10];
void dfs(int m){
if(!n) return ;
if(ring[m-1]) dfs(m-1);
for(int i=m-2;i>=1;i--)
if(!ring[i]) dfs(i);
if(!n) return ;
ring[m]=!ring[m];
n--;
}
int main()
{
#ifdef local
freopen("input.txt","r",stdin);
#endif
scanf("%d",&n);
memset(ring,0,sizeof(ring));
for(int i=9;i>=1;i--)
if(!ring[i]) dfs(i);
if(n) printf("-1\n");
else{
for(int i=1;i<=9;i++)
printf("%d",!ring[i]);
}
return 0;
}
问题D:2的幂次方
时间限制: 1 Sec 内存限制: 64 MB
题目描述
任何一个正整数都可以用2的幂次方表示。例如:
137
=
2
7
+
2
3
+
2
0
137=2^7+2^3+2^0
137=27+23+20
同时约定方次用括号来表示,即
a
b
a^b
ab 可表示为
a
(
b
)
a(b)
a(b)。
由此可知,
137
137
137可表示为:
2
(
7
)
+
2
(
3
)
+
2
(
0
)
2(7)+2(3)+2(0)
2(7)+2(3)+2(0)
进一步:
7
=
2
2
+
2
+
2
0
(
2
1
用
2
表
示
)
3
=
2
+
2
0
7=2^2+2+2^0 (2^1用2表示) 3=2+2^0
7=22+2+20(21用2表示)3=2+20
所以最后
137
137
137可表示为:
2
(
2
(
2
)
+
2
+
2
(
0
)
)
+
2
(
2
+
2
(
0
)
)
+
2
(
0
)
2(2(2)+2+2(0))+2(2+2(0))+2(0)
2(2(2)+2+2(0))+2(2+2(0))+2(0)
又如:
1315
=
2
1
0
+
2
8
+
2
5
+
2
+
2
0
1315=2^10 +2^8 +2^5 +2+2^0
1315=210+28+25+2+20
所以
1315
1315
1315最后可表示为:
2
(
2
(
2
+
2
(
0
)
)
+
2
)
+
2
(
2
(
2
+
2
(
0
)
)
)
+
2
(
2
(
2
)
+
2
(
0
)
)
+
2
+
2
(
0
)
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
输入
一行,一个正整数(n≤20000)
输出
符合约定的n的0,2表示(在表示中不能有空格)
样例输入
137
样例输出
2(2(2)+2+2(0))+2(2+2(0))+2(0)
解题思路:
①看见别人有暴力打表解决问题的;
②递归的思路:
明确目的:求n的二次幂表示的各个指数,顺序是从高到低,之后将各个指数再进行“拆分操作”。
递归函数:
参数:当前的n值和递归的深度(2的指数)。
终止条件:n==1的时候
函数print(n,0)就是求n的“2的幂次方”表示,所以,递归调用print(n,0)就可以解决问题。(当然,当n<=2的时候,直接按格式输出就可以。)
#include <bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include <cstdio>
//#define local
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N = 1e4+5;
const int inf = 0x3f3f3f3f;
const int mod = 998244353;
int n;
void print(int n,int deep){
if(n==1){
if(deep==0){
printf("2(0)");
return ;
}
if(deep==1){
printf("2");
return ;
}
if(deep==2){
printf("2(2)");
return ;
}
if(deep>2){
printf("2(");
print(deep,0);
printf(")");
}
}
else{
print(n/2,deep+1);
if(n&1){
if(deep==0) printf("+2(0)");
if(deep==1) printf("+2");
if(deep==2) printf("+2(2)");
if(deep>2){
printf("+2(");
print(deep,0);
printf(")");
}
}
}
}
int main()
{
#ifdef local
freopen("input.txt","r",stdin);
#endif
scanf("%d",&n);
print(n,0);
return 0;
}