模拟 枚举 递归总结(1. 闰年判断 2.这是第几天 3.机器人模拟 4.页码统计 5.顺子 6.字符串 7.区间和统计 8.斐波那契数列 9.汉诺塔)

相关例题

1. 闰年判断

题目描述
闰年分为普通闰年和世纪闰年。
普通闰年:公历年份是4的倍数的,一般是闰年(如2004年就是闰年)。
世纪闰年:公历年份是整百数的,必须是400的倍数才是闰年(如1900年不是世纪闰年,2000年是世纪闰年)。
给出一个年份y,如果y是闰年,则输出"Yes", 否则输出"No"

输入
第一行输入一个整数n,表示样例个数,每个样例包含一个单独一行的数字y,表示需要判断的年份。

输出
如果y是闰年,则输出 一行"Yes", 否则输出一行"No"。

样例输入
4
2004
2005
1900
2000
样例输出
Yes
No
No
Yes
题目分析:本题判断闰年,则只需要知道什么情况下输入的数字是闰年即可:
由题中所给条件可知,闰年年份满足:不是整百的时候,是4的倍数;是整百的时候,必须是400的倍数。由此可知只需要分两种情况讨论,之后分别判断是否是4或者400的倍数。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        int y;
        cin >> y;
        if (y % 100 != 0) {//如果不是整百
            if (y % 4 == 0) {
                cout << "Yes" << endl;//如果是4的倍数就输出yes
            }
                else cout << "No" << endl;//不是就输出no
        }
        if (y % 100 == 0) {//如果是整百
            if (y % 400 == 0) {
                cout << "Yes" << endl;//如果是400的倍数就输出yes
            }
            else cout << "No" << endl;//不是就输出no
        }
    }
    return 0;
}

2.这是第几天

题目描述
输入三个数字, y, m, d,表示y年m月d日,例如,输入 1997 2 1 表示1997年2月1日,
求出y m d表示的日期是今年的第多少天。

输入
第一行一个数字n表示样例个数。
对于每一个样例,包含三个由空格间隔的一行数字,表示需要处理的年、月、日。

输出
对于每一个 “y m d” 输出当天是今年的第k天。每个输出占一行。

样例输入
2
1997 2 1
1996 3 1
样例输出
32
61
题目分析
本题输入年月日,求出表示的日期是那一年的第多少天。这个问题应该分是否是闰年和月份讨论,可以开数组,储存平年的每个月份分别有多少天,之后判断是否是闰年而且判断是否比2月大,如果是就加1,不是就不用处理。

#include <bits/stdc++.h>
using namespace std;
int panduan(int a)//判断是否是闰年
{
    if (a % 100 != 0 && a % 4 == 0)
        return 1;
    if (a % 100 == 0 && a % 400 == 0)
        return 1;
    return 0;
}
int main()
{
    int n;
    cin >> n;
    while (n--) {
        int y, m, d, k = 0;
        cin >> y >> m >> d;
        int month[13] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        for (int i = 1; i < m; i++) {//从1开始,当所处月份小于i时
            k += month[i - 1];//加之前月份的天数
        }
        k += d;//加上这个月已经过了的天数
        if (panduan(y) == 1 && m > 2) {//如果是闰年而且比2月大就加一天
            k += 1;
        }
        cout << k << endl;
    }
    return 0;
}

3.机器人模拟

题目描述
一个没有体积的机器人最开始在(0, 0)点。WSAD分别表示上、下、左、右移动。例如机器人一开始在(0, 0)点,W操作会使机器人走向(0, 1), D操作会使机器人走向(1, 0), 请求出机器人经过k轮操作后所在的位置。

输入
输入第一行一个数字T,表示样例数。对于每个样例,每行一个只包含"WASD"的字符串,表示机器人的行驶轨迹。

输出
对于每个样例,输出两个数字"x y"表示机器人最终到达的位置。

样例输入
2
WSDA
AAAAA
样例输出
0 0
-5 0
题目分析
a,b两个数字初始化为0,之后只需要判断输入字符串s中的每个字符是WSDA中的哪个,WS分别使输入的b加或减1,DA分别使输入的a加或减1,最后输出改变后的a,b即可。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        int a = 0, b = 0;//初始化ab
        string s;
        cin >> s;//输入字符串
        int size = s.size();
        for (int i = 0; i < size; i++) {//遍历字符串中的每个元素
           if (s[i] == 'W') b++;
           if (s[i] == 'S') b--;
           if (s[i] == 'A') a--;
           if (s[i] == 'D') a++;//分别改变ab的值
       }
        cout << a << " " << b << endl;//输出
    }
    return 0;
}

4.页码统计

题目描述
小孟在给他的PPT标页码,小孟没有高超的百度技巧,他选择手动输入页码。假定他一共有k页PPT,求小孟在输入PPT页码时,按键0-9的每个按键需要按多少次?
输入
第一行输入一个数字T表示样例个数。
对于每个样例,输入一个整数K,表示页数。

输出
对于每个样例,输出用空格分隔的10个数,表示[0,9]中,每个数字出现的个数。
样例输入
2
10
5
样例输出
1 2 1 1 1 1 1 1 1 1
0 1 1 1 1 1 0 0 0 0
提示
k <= 1000000
题目分析
a[10]代表0~9每个数字出现的次数,先分割k为6位数为num[i],当num[i]!=0时,对i及比i位低的数都进行a[num[i]]++,也就是对k的每一位数都进行计数,之后进行k–,重复上述内容知道k = 0。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        int k;
        cin >> k;
        int a[10];
        memset(a, 0, 10);//初始化数组a
        while (k)
        {
            int num[7];
            num[0] = 0;
            num[1] = k / 100000;
            num[2] = k % 100000 / 10000;
            num[3] = k % 10000 / 1000;
            num[4] = k % 1000 / 100;
            num[5] = k % 100 / 10;
            num[6] = k % 10;      //分割k中的每一个元素
            for (int i = 0, l = 1; i < 7 && l > 0; i++)
            if (num[i]) {
                    for (int m = i; m < 7; m++)
                    a[num[m]]++;//对k第一位数之后的数进行计数
                    l--;//计数完毕之后结束这个循环,执行k--的操作
            }
            k--;//相当于从后往前一个数一个数遍历
        }
        for (int j = 0; j < 9; j++)
            cout << a[j] << " ";
            cout << a[9] << endl;//输出每一个数的遍历次数
    }
    return 0;
}

5.顺子

题目描述
一副去除大小王的扑克中有4种花色,用1, 2, 3, 4表示;每种花色有13张牌,用1-13表示。
但是这副扑克牌丢失了一些牌,此时从扑克中抽出三张牌,询问有多少种抽法抽出顺子?(顺子对花色不敏感)

输入
第一行输入一个数字T表示样例数。
对于每组样例:第一行输入一个数字n表示丢失牌的数量。
2-n+1行每行输入两个数字 a b表示丢失了花色a的第b张。(1 <= a <= 4)

输出
对于每个样例,输出一个数R表示顺子的可能抽法。

样例输入
1
1
1 13
样例输出
688
提示
顺子的定义为,连续三张的牌,但是不能越过13(K)
即, (13, 1, 2) 和 (12, 13, 1)均不算顺子。
(1, 2, 3)算顺子。
题目中, 丢失了第一种花色的13,最终可以抽出688种顺子。
题目描述
首先建立两个数组,数组a用来记录每种花色每张牌是否被拿走,数组g用来确定不同花色但是序号相同的牌缺少的个数;之后只需要用4-g[i]来确定这个序号的牌还剩下的个数;使用for循环,对每三张牌进行全排列,最后的结果就是每一次循环所得的结果全部加起来。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        int c;
        long long int h = 0;//注意最后输出的可能是非常大的数
        int a[4][13], g[13];
        memset(g, 0, sizeof(g));//初始化数组
        memset(a, 0, sizeof(a));//初始化数组
        cin >> c;//输入缺少的牌数
        while (c--)
        {
            int b, d;//b-1是花色,d-1是这个花色对应的序号
            cin >> b >> d;
            a[b - 1][d - 1] = 1;//代表这张牌缺少
        }
        for (int i = 0; i < 13; i++)
        {
            for (int j = 0; j < 4; j++)//遍历4种花色,13张牌
            {
                if (a[j][i] == 1) g[i]++;//如果这张序号的牌缺少就g[i]++
            }
        }
        for (int i = 0; i < 11; i++)
            h = h + (4 - g[i]) * (4 - g[i + 1]) * (4 - g[i + 2]);
       cout << h << endl;//上边两个*连接的式子代表相邻三张牌的全排列,遍历
    }
    return 0;
}

6.字符串

题目描述
给定连个字符串a和 b,求出b在a中第一次出现的位置。如果b没有在a中出现过,则输出-1。

输入
第一行包含一个数字T表示样例个数,对于每组样例,包含两个用空格分隔的字符串a,只包含小写字母。

输出
对于每组样例,输出b在a中第一次出现的位置。

样例输入
3
abc b
aaaab ab
ab d
1
3
-1
样例输出
1
3
-1
题目分析
首先定义两个字符串,之后输入两个字符串;之后使用find函数,如果能找到,就输出s1.find(s2),也就是s2在s1中第一次出现的位置;如果不能找到就输出-1。(注意最外面有循环)

#include <bits/stdc++.h>
using namespace std;
int main() {
    int n;
    cin >> n;
    while (n--)
    {
        string s1;
        string s2;
        cin >> s1 >> s2;//输入两个字符串
        if(s1.find(s2) != string::npos) {//如果能找到s2
            cout << s1.find(s2) << endl;//输出s2在s1中第一次出现的位置
        }
        else {//如果找不到s2
            cout << "-1" << endl;//输出-1
        }
    }
	return 0;
}

7.区间和统计

题目描述
给定一个包含n个元素的数组,数组中元素ai保证 -1000 < ai < 1000。在数组中,从l到r(l <= r)的所有数叫做数组的一个[l, r]子区间,你需要求出,所有子区间中,和为k的区间一共有多少个。

输入
第一行包含一个整数T表示样例个数。
对于每一个样例,第一行输入两个数字,n, p其中n表示数组的长度, p代表区间和。
第二行包含n个数字表示数组的元素。

输出
对于每一个样例,输出一个数字表示和为p的子区间个数。

样例输入
1
5 8
4 4 4 4 4
样例输出
4
提示
所有的ai均为整数。
保证 n <= 1000
题目分析
第一个输入的数是数组的长度,第二个输入的数是区间内元素的和;之后下一行输入这个数组,在这个数组内找和等于第二个输入的数的区间,输出这样的区间个数——
容易知道只需要设置两个for循环,从第一个for循环的起点对应的元素开始加,如果能正好和第二个输入的数相等,区间个数加1,否则一直加,直到相等或者超出数组长度,跳出内部for循环,在外层for循环实现起点向后推移,之后多次遍历,不重不漏。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        int a, b, count = 0;
        cin >> a >> b;
        int arr[a];
        for (int i = 0; i < a; i++)
            cin >> arr[i];//输入数组内各元素的值
        for (int j = 0; j < a; j++) {//从零开始遍历
            int d = 0;//d要储存数组内某些区间元素的和,先初始化为0
            for (int k = j; k < a; k++) {//两层循环防止重复遍历
                d += arr[k];//d加上arr[k],以便将来作比较
                if (d == b) {//如果现在的和就是第二个输入的数
                    count ++;//这样的区间个数加1
                }
            }
        }
        cout << count << endl;//输出这样的区间个数
    }
    return 0;
}

8.斐波那契数列

题目描述
斐波那契数列中, a0=0, a1=1, ,对于k > 1, ak = ak-1 + ak-2 求出斐波那契数列的第n项。

输入
第一行输入一个整数T表示样例个数,对于每个样例,输入一个整数n表示需要求出第n项斐波那契数字。

输出
对于每个样例,输出一个数字num表示第n项斐波那契数字。

样例输入
3
1
2
3
样例输出
1
1
2
提示
n <= 60
题目分析
首先明确斐波那契数列的递推公式是:f[0] = 0,f[1] = 1,之后有f[i] = f[i - 1] + f[i - 2],容易知道只需要输入要求的项的序号,之后用for循环求得,输出即可。(注意最外层有循环)

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        int a;//输入需要求的位数f[a]
        long long int f[100];//注意之后可能有很大的数
        f[0] = 0, f[1] = 1;//斐波那契数列的要求
        cin >> a;
        for (int i = 2; i <= a; i++)//只需要算到f[a]即可
        {
            f[i] = f[i - 1] + f[i - 2];//斐波那契数列的递推公式
        }
        cout << f[a] << endl;//输出所求
    }
    return 0;
}

9.汉诺塔

题目描述
汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

输入
第一行包含一个整数T表示样例数。
对于每个样例,输入一个n表示汉诺塔的级数。

输出
对于每个样例,输出一个整数表示最少需要移动的次数。

样例输入
3
1
2
3
样例输出
1
3
7
提示
n <= 40
题目分析
明确汉诺塔问题其实就是求2^n - 1,对于输入的a(也就是n),只需要在for循环下a次重复乘2,之后给结果减1,输出即可。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        int a;
        cin >> a;
        long long int b = 1;//注意最后b可能是很大的数,所以要long long
        for (int i = 0; i < a; i++)
              b *= 2;
        b -= 1;//计算2^n - 1
        cout << b << endl;//输出即可
    }
    return 0;
}
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值