NENU OJ算法2例题 递归A

NENU OJ算法2例题

剩余oj例题的代码思路已更新到本人网站上,指路:DODOLA’s

这学期写算法2并不想写详细思路(出于ddl再也不用关心小组啦的自由),不过如果有想交流的也可以评论区或者私信,学校oj的题大多比较简单,这里的所有代码或许只保证通过学校的弱测试数据,因为其他地方OJ我还没有试过

目录:

算法2递归A

1241: A001 猴子吃桃

题目描述

猴子第1天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第2天又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半另加一个。到第10天早上想再吃时,就只剩下一个桃子了。求第1天共摘了多少个桃子。

输入

输入第一行为正整数n,为测试数据组数。后面n行为测试数据,每组测试数据包括两个整数m,k,分别表示第m(m>1)天后剩余的桃子数k(k>=0)。

输出

输出猴子第一天摘的桃子数,每组数据占一行。

样例输入

2
2  2
3  0

样例输出

6
6
AC代码
#include<bits/stdc++.h>
using namespace std;
int main() {
    int n;cin >> n;
    while (n--) {
        int m, k;cin >> m >> k;
        int sum = k;
        for (int i = 0;i < m - 1;i++) {
            sum++;
            sum *= 2;
        }
        cout << sum << endl;
    }

    return 0;
}

1242: A002 最大公约数

题目描述

输入两个正整数,求其最大公约数。
数论中有一个求最大公约数的算法称为辗转相除法,又称欧几里德算法。其基本思想及执行过程为(设m为两正整数中较大者,n为较小者):
(1)令u=m,v=n;
(2)取u对v的余数,即r=u%v,如果r的值为0,则此时v的值就是m和n的最大公约数,否则执行第(3)步;
(3)u=v,v=r,即u的值为v的值,而v的值为余数r。并转向第(2)步。

输入

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括两个正整数m和n。

输出

n行,每行输出对应一个输入。输出应是一个正整数,为m和n的最大公约数。

样例输入

2
48 32
15 5

样例输出

16
5
AC代码
#include<bits/stdc++.h>
using namespace std;
int main() {
    int t;cin >> t;
    while (t--) {
        int m, n;cin >> m >> n;
        int yu = m % n;
        while (yu) {
            m = n;n = yu;
            yu = m % n;
        }
        cout << n << endl;
    }

    return 0;
}

1243: A003 经典的Hanoi(汉诺塔)问题

题目描述

有一个汉诺塔,塔内有A,B,C三个柱子。起初,A柱上有n个盘子,依次由大到小、从下往上堆放,要求将它们全部移到C柱上;在移动过程中可以利用B柱,但每次只能移到一个盘子,且必须使三个柱子上始终保持大盘在下,小盘在上的状态。要求编程输出移动的步骤。

输入

输入文件中包含多行,每行为一个整数n,代表初始A柱子上的盘子的个数。

输出

对输入文件中的每个整数n列出具体的汉诺塔移动步骤。两组输出之间有一空行。

样例输入

3
1

样例输出

A-->C
A-->B
C-->B
A-->C
B-->A
B-->C
A-->C

A-->C
AC代码
#include<bits/stdc++.h>
using namespace std;
void hanoi(int n, int from, int to) {
    if (n == 0) return;     // 全部移完,终止递归
    // 把from位置上的上面的n-1个移到不是from也不是to的位置
    hanoi(n - 1, from, (3 - from - to));
    // 移动最底下的最大的那个,并输出记录
    cout << char(from + 'A') << "-->" << char(to + 'A') << endl;
    // 把之前移走的n-1个移到to位置
    hanoi(n - 1, (3 - from - to), to);
}
int main() {
    int n;
    while (cin >> n) {
        hanoi(n, 0, 2);
        cout << "\n";
    }

    return 0;
}

1244: A004 菲波那契数列

题目描述

菲波那契数列是指这样的数列: 数列的第一个和第二个数都为1,接下来每个数都等于前面2个数之和。给出一个正整数a,要求菲波那契数列中第a个数是多少。

输入

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a(1 <= a <= 20)。

输出

输出有n行,每行输出对应一个输入。输出应是一个正整数,为菲波那契数列中第a个数的大小。

样例输入

4
5
2
19
1

样例输出

5
1
4181
1
AC代码
#include<bits/stdc++.h>
using namespace std;

int fib(int n) {
    if (n == 1 || n == 2)return 1;
    return fib(n - 1) + fib(n - 2);
}

int main() {
    int t;cin >> t;
    while (t--) {
        int a;cin >> a;
        cout << fib(a) << endl;
    }

    return 0;
}

1245: A005 另一个Fibonacci数列

题目描述

定义另外一个Fibonacci数列:F(0)=7,F(1)=11,F(n)=F(n-1)+F(n-2),(n≥2)。

输入

输入文件中包含多行,每行为一个整数n,n<1000000。

输出

对输入文件中的每个整数n,如果F(n)能被3整除,输出yes,否则输出no。

样例输入

0
1
2
3

样例输出

no
no
yes
no
AC代码
#include<bits/stdc++.h>
using namespace std;
int main() {
    long long na;
    while (cin >> na) {
        if (na % 8 == 2 || na % 8 == 6)cout << "yes\n";
        else cout << "no\n";
    }

    return 0;
}

1246: A006 分形(Fractal)

题目描述

分形是存在“自相似”的一个物体或一种量,从某种技术角度来说,这种“自相似”是全方位的。
盒形分形定义如下:
度数为1的分形很简单,为:
X

度数为2的分形为:

X X

X

X X

如果用B(n-1)代表度数为n-1的盒形分形,则度数为n的盒形分形可以递归地定义为:

B(n-1) B(n-1)

B(n-1)

B(n-1) B(n-1)

你的任务是输出度数为n的盒形分形。

输入

输入文件包含多个测试数据,每个测试数据占一行,包含一个正整数n,n ≤ 7。输入文件的最后一行为-1,代表输入结束。

输出

对每个测试数据,用符号“X”表示输出盒形分形。在每个测试数据对应的输出之后输出一个短划线符号“-”,在每行的末尾不要输出任何多余的空格,否则得到的是“格式错误”的结果。

样例输入

2
3
-1

样例输出

X X
 X
X X
-
X X   X X
 X     X
X X   X X
   X X
    X
   X X
X X   X X
 X     X
X X   X X
AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxlen = pow(3, 8);
// string mp[maxlen];
char mp[maxlen][maxlen];
int xpos[maxlen];

void tocpyRec(int deg, int tox, int toy,int fillblank) {
    int len = pow(3, deg - 1);
    // 左上角标记
    for (int i = 0;i < len;i++) {
        for (int j = 0;j < len;j++) {
            // cout << mp[i][j] << ":" << i << "-" << j << endl;
            if (fillblank)
                mp[tox * len + i][toy * len + j] = ' ';
            else
                mp[tox * len + i][toy * len + j] = mp[i][j];
        }
    }
}

void fw(int deg) {
    if (deg > 1) {
        fw(deg - 1);
    }
    for (int i = 0;i < 3;i++) {
        for (int j = 0;j < 3;j++) {
            if ((i + j) % 2 == 0 && (i || j)) {
                // 有内容的块坐标
                tocpyRec(deg - 1, i, j, 0);
            }
            else if (i || j) {
                tocpyRec(deg - 1, i, j, 1);
            }
        }
    }
}

int main() {
    mp[0][0] = 'X';
    int n;
    int flag = 0;
    while (cin >> n && n != -1) {
        if (flag)cout << "-\n";
        flag = 1;
        fw(n);
        int len = pow(3, n - 1);
        for (int i = 0;i < len;i++) 
            for (int j = 0;j < len;j++) 
                if (mp[i][j] == 'X')
                    xpos[i] = j;
        
        for (int i = 0;i < len;i++) {
            for (int j = 0;j <= xpos[i];j++) {
                cout << mp[i][j];
            }
            cout << endl;
        }
    }

    return 0;
}

1247: A007 二叉树

题目描述

如图所示,由正整数1, 2, 3, …组成了一棵无限大的二叉树。从某一个结点到根结点(编号是1的结点)都有一条唯一的路径,比如从10到根结点的路径是(10, 5, 2, 1),从4到根结点的路径是(4, 2, 1),从根结点1到根结点的路径上只包含一个结点1,因此路径就是(1)。对于两个结点x和y,假设他们到根结点的路径分别是(x1, x2, … ,1)和(y1, y2, … ,1)(这里显然有x = x1,y = y1),那么必然存在两个正整数i和j,使得从xi 和 yj开始,有xi = yj , xi + 1 = yj + 1, xi + 2 = yj + 2,… 现在的问题就是,给定x和y,要求xi(也就是yj)。

A007.jpg

输入

输入有多行,每行包括两个正整数x和y,这两个正整数都不大于1000。

输出

每行输出只有一个正整数xi。

样例输入

10 4

样例输出

2
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N = 12;
int ax[N], ay[N];
int main() {
    int x, y;
    // 找重合的路径
    while (cin >> x >> y) {
        int kx = 0;
        while (x) {
            ax[kx++] = x % 2;
            x /= 2;
        }
        int ky = 0;
        while (y) {
            ay[ky++] = y % 2;
            y /= 2;
        }
        int kmii = kx > ky ? ky : kx;
        int ans = 0;
        for (int i = 1;i <= kmii;i++) {
            if (ax[kx - i] == ay[ky - i]) {
                ans <<= 1;
                ans += ax[kx - i];
            }
            else break;
        }
        cout << ans << endl;
    }

    return 0;
}

1248: A008 波兰表达式

题目描述

波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的波兰表示法为+ 2 3。波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的波兰表示法为* + 2 3 4。本题求解波兰表达式的值,其中运算符包括+ - * /四个。

输入

输入第一行为一个整数n,然后是n行,每行为一组测试数据,其中运算符和运算数之间都用空格分隔,运算数是浮点数。

输出

输出n行,每行表达式的值,保留3位小数输出。

样例输入

1
* + 11.0 12.0 + 24.0 35.0

样例输出

1357.000
AC代码
#include<bits/stdc++.h>
using namespace std;

double dox() {
    string st;cin >> st;
    switch (st[0])
    {
    case '+':
        return dox() + dox();
    case '-':
        return dox() - dox();
    case '/':
        return dox() / dox();
    case '*':
        return dox() * dox();
    default:break;
    }
    return atof(st.c_str());
}

int main() {
    int t;cin >> t;
    while (t--) {
        cout << fixed << setprecision(3) << dox() << endl;
    }

    return 0;
}

1249: A009 放苹果

题目描述

把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法(用K表示)?注意:5,1,1和1,5,1 是同一种分法。

输入

第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1 <= M,N <= 10。

输出

对输入的每组数据M和N,用一行输出相应的K。

样例输入

1
7 3

样例输出

8
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N = 15;
int dp[N][N];

int divx(int apl, int pla) {
    if (apl == 0 || pla == 1)
        return dp[apl][pla] = 1;
    if (pla > apl)
        return dp[apl][pla] = divx(apl, apl);
    return dp[apl][pla] = divx(apl, pla - 1) + divx(apl - pla, pla);
}

int main() {
    int t;cin >> t;
    int m, n;
    while (t--) {
        cin >> m >> n;
        cout << divx(m, n) << endl;
    }

    return 0;
}

1250: A010 递归练习1

题目描述

有5个人坐在一起,问第5个人多少岁?他说比第4个人大两岁。问第4个人的岁数,他说比第3个人大两岁。问第3个人的岁数,又说比第2个人大两岁。问第2个人的岁数,说比第1个人大两岁。最后问第1个人的岁数,他说是10岁。请问第5个人多少岁?

输入

输入有多行,每行3个整数,依次为m,n,k。m表示一共有几个人,n表示大的岁数,k表示第一个人的岁数。

输出

输出第m个人的岁数,每个一行。

样例输入

5 2 10

样例输出

18
AC代码
#include<bits/stdc++.h>
using namespace std;

int m, n, k;
int age(int ind) {
    if (ind == 1)return k;
    return age(ind - 1) + n;
}

int main() {
    while (cin >> m >> n >> k) {
        cout << age(m) << endl;
    }

    return 0;
}

1251: A011 递归练习2

题目描述

根据递推式子C(m,n)=C(m-1,n)+C(m-1,n-1),求组合数C(m,n)。注意递推的终止条件是C(m,1)=m;以及一些m和n取值的一些特殊情况,如m < 0或n < 0或m < n时,C(m,n)值为0,m和n相等时,C(m,n)=1等。

输入

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数m和一个正整数n。

输出

输出组合数C(m,n)。

样例输入

2
1 100
100 1

样例输出

0
100
AC代码
#include<bits/stdc++.h>
using namespace std;

int C(int m, int n) {
    if (n == 1)return m;
    if (m < 0 || n < 0 || m < n)return 0;
    if (m == n)return 1;
    return C(m - 1, n) + C(m - 1, n - 1);
}

int main() {
    int t;cin >> t;
    while (t--) {
        int m, n;cin >> m >> n;
        cout << C(m, n) << endl;
    }

    return 0;
}

1252: A012 递归练习3

题目描述

核反应堆中有α和β两种粒子。每秒钟内一个α粒子可以产生3个β粒子,而一个β粒子可以产生1个α粒子和2个β粒子。若在t=0时刻反应堆中有一个α粒子,求t时刻反应堆中分别有多少个α粒子和β粒子。

输入

输入有多个整数t,每个一行。

输出

输出t时刻反应堆里分别有多少个α粒子和β粒子。

样例输入

6

样例输出

183 546
AC代码
#include<bits/stdc++.h>
using namespace std;

pair<int, int> qut(int n) {
    if (n == 0)return make_pair(1, 0);
    int tempa = qut(n - 1).first, tempb = qut(n - 1).second;
    int a = tempb, b = 3 * tempa + 2 * tempb;
    return make_pair(a, b);
}

int main() {
    int t;
    while (cin >> t) {
        cout << qut(t).first << " " << qut(t).second << endl;
    }

    return 0;
}

插一句:这里用了pair数据类型,或许有同学并没有接触到…一般函数会返回1个值,有时候想返回两个或以上的时候可以试试自定义struct数据类型,再去定义一个struct的函数,不过c++自有一个pair可以用,还是挺方便的。

1253: A013 红与黑

题目描述

有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。

输入

包括多个数据集合。每个数据集合的第一行是两个整数W和H,分别表示x方向和y方向瓷砖的数量。W和H都不超过20。在接下来的H行中,每行包括W个字符。每个字符表示一块瓷砖的颜色,规则如下
1)‘.’:黑色的瓷砖;
2)‘#’:白色的瓷砖;
3)‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每个数据集合中唯一出现一次。
当在一行中读入的是两个零时,表示输入结束。

输出

对每个数据集合,分别输出一行,显示你从初始位置出发能到达的瓷砖数(记数时包括初始位置的瓷砖)。

样例输入

6 9 
....#. 
.....# 
...... 
...... 
...... 
...... 
...... 
#@...# 
.#..#. 
0 0

样例输出

45
AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxh = 25;
string mp[maxh];
int dx[4] = { -1,0,1,0 }, dy[4] = { 0,1,0,-1 };

int w, h;
int move(int x, int y, int allstep) {
    for (int i = 0;i < 4;i++) {
        int nx = x + dx[i], ny = y + dy[i];
        if (nx > -1 && nx<h && ny>-1 && ny < w && mp[nx][ny] == '.'){
            mp[nx][ny] = '#';
            allstep = move(nx, ny, allstep + 1);
        }
    }
    return allstep;
}

int main() {
    while (cin >> w >> h && w != 0 && h != 0) {
        int si, se;
        for (int i = 0;i < h;i++) {
            cin >> mp[i];
            if (mp[i].find("@") != string::npos) {
                si = i;se = mp[i].find("@");
            }
        }
        int steps = move(si, se, 1);
        cout << steps << endl;
    }

    return 0;
}

1254: A014 城堡问题

题目描述

1 2 3 4 5 6 7
#############################

1 # | # | # | | #

#####—#####—#—#####—#

2 # # | # # # # #

#—#####—#####—#####—#

3 # | | # # # # #

#—#########—#####—#—#

4 # # | | | | # #

#############################

(图 1)

‘#’ = Wall
‘|’ = No wall
‘-’ = No wall

图1是一个城堡的地形图。请你编写一个程序,计算城堡一共有多少房间,最大的房间有多大。城堡被分割成m*n(m≤50,n≤50)个方块,每个方块可以有0~4面墙。

输入

程序从标准输入设备读入数据。第一行是两个整数,分别是南北向、东西向的方块数。在接下来的输入行里,每个方块用一个数字(0≤p≤50)描述。用一个数字表示方块周围的墙,1表示西墙,2表示北墙,4表示东墙,8表示南墙。每个方块用代表其周围墙的数字之和表示。城堡的内墙被计算两次,方块(1,1)的南墙同时也是方块(2,1)的北墙。输入的数据保证城堡至少有两个房间。

输出

城堡的房间数、城堡中最大房间所包括的方块数。

样例输入

4
7
11 6 11 6 3 10 6
7 9 6 13 5 15 5
1 10 12 7 13 7 5
13 11 10 8 10 12 13

样例输出

5
9
AC代码
#include<bits/stdc++.h>
using namespace std;
const int N = 60;
int wall[N][N], fw[N][N];
int roomnum = 0, sizea = 0;
void dfs(int x, int y) {
    // 查找点(x,y)的信息
    if (fw[x][y]) return;
    sizea++;
    fw[x][y] = roomnum;
    if ((wall[x][y] & 1) == 0)dfs(x, y - 1);
    if ((wall[x][y] & 2) == 0)dfs(x - 1, y);
    if ((wall[x][y] & 4) == 0)dfs(x, y + 1);
    if ((wall[x][y] & 8) == 0)dfs(x + 1, y);
}

int main() {
    int h, w;cin >> h >> w;
    for (int i = 1;i <= h;i++){
        for (int j = 1;j <= w;j++){
            cin >> wall[i][j];
        }
    }
    int maxroom = 0;
    for (int i = 1;i <= h;i++) {
        for (int j = 1;j <= w;j++) {
            if (!fw[i][j]) {
                // (i,j)没被找过(新的area)
                roomnum++;
                dfs(i, j);
                maxroom = max(maxroom, sizea);
                sizea = 0;
            }
        }
    }
    cout << roomnum << endl << maxroom << endl;

    return 0;
}

/*
  2
1   4
  8
*/

1255: A015 分解因式

题目描述

给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * … * an,并且1 < a1 <= a2 <= a3 <= … <= an,问这样的分解的种数有多少。注意到a = a也是一种分解。

输入

第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a (1 < a < 32768)。

输出

n行,每行输出对应一个输入。输出应是一个正整数,指明满足要求的分解的种数。

样例输入

2
2
20

样例输出

1
4
AC代码
#include<bits/stdc++.h>
using namespace std;
int ans = 0;
void dfs(int tar, int now) {
    if (tar != 1) {
        for (int i = now;i <= tar;i++)
            if (tar % i == 0)
                dfs(tar / i, i);
    }
    else {
        ans++;return;
    }
}

int main() {
    int t;cin >> t;
    while (t--) {
        ans = 0;
        int n;cin >> n;
        if (n == 2) {
            cout << 1 << endl;
            continue;
        }
        dfs(n, 2);
        cout << ans << endl;
    }
    

    return 0;
}

1256: A016 数字拼凑

题目描述

现在给你这样一个任务,要求找出具有下列性质数的个数(包含输入的正整数 n)。
先输入一个正整数 n(n <= 500),然后对此正整数按照如下方法进行处理:

  1. 不作任何处理;
  2. 在它的左边拼接一个正整数,但该正整数不能超过原数的一半或者是上一个被拼接数的一半;
  3. 加上数后,继续按此规则进行处理,直到不能再加正整数为止。

输入

一个正整数n。

输出

一个正整数,表示具有该性质数的个数。

样例输入

6

样例输出

6
AC代码
#include<bits/stdc++.h>
using namespace std;
int fx[1010];
int f(int n) {
    if (n == 1)return 1;
    if (fx[n])return fx[n];

    int cnt = 0;
    for (int i = 1;i <= n / 2;i++)
        cnt += f(i);
    return fx[n] = cnt + 1;
}

int main() {
    int n;
    cin >> n;
    cout << f(n) << endl;

    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值