杭州电子科技大学acm基础100题 2000~2099 hdu acm basic 100(持续更新)

代码开源在GitHub上,持续在此更新题解。
2007题注意输入的两组数据前后大小关系,一定要保持前一个数字小于第二个数字


2024/2/19
此次更新2010~2019题
着重注意2017,2018两题。

// Problem Description(2017)
// 对于给定的一个字符串,统计其中数字字符出现的次数。
// Input
// 输入数据有多行,第一行是一个整数n,表示测试实例的个数,后面跟着n行,每行包括一个由字母和数字组成的字符串。
// Output
// 对于每个测试实例,输出该串中数值的个数,每个输出占一行。
// Sample Input
// 2
// asdfasdf123123asdfasdf
// asdf111111111asdfasdfasdf
// Sample Output
// 6
// 9
#include <iostream>
#include <cstring>
using namespace std;

int main() {
    int n;
    cin>>n;
    cin.ignore();
    while (n--) {
        char str[1000];
        cin.getline(str, 1000);
        int count = 0;
        for (int i = 0; i < strlen(str); i++) 
        {
            if (str[i]>='0'&&str[i]<='9') 
            {
                count++;
            }
        }
        cout << count << endl;
    }
    return 0;
}

这段代码若去掉cin.ignore()则会出现问题
问题出在使用 cin >> n 读取 n 的时候,输入缓冲区中的换行符没有被清除,导致第一个 getline() 读取了换行符而不是预期的字符串。
解决这个问题的方法之一是在读取 n 之后使用 cin.ignore() 来清除输入缓冲区中的换行符,或者直接使用 getline() 来读取 n。另外,也可以在读取字符串之前使用 cin.ignore() 来清除换行符。

// Problem Description
// 有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?
// Input
// 输入数据由多个测试实例组成,每个测试实例占一行,包括一个整数n(0<n<55),n的含义如题目中描述。
// n=0表示输入数据的结束,不做处理。
// Output
// 对于每个测试实例,输出在第n年的时候母牛的数量。
// 每个输出占一行。
// Sample Input
// 2
// 4
// 5
// 0
// Sample Output
// 2
// 4
// 6
#include <iostream>
using namespace std;

int main() 
{
    int cows[55] = {0, 1, 2, 3, 4};
    for (int i = 5; i < 55; i++) 
    {
        cows[i] = cows[i - 1] + cows[i - 3];
    }
    int n;
    while (cin >> n && n != 0) 
    {
        cout << cows[n] << endl;
    }
    return 0;
}

这个问题为一个数学问题,在求解时可定义一个数组,采用递归的方式求出后续数组中数据的大小。类似斐波那契数列求解。


2024/2/23

Problem Description
输入一个字符串,判断其是否是C的合法标识符。
Input
输入数据包含多个测试实例,数据的第一行是一个整数n,表示测试实例的个数,然后是n行输入数据,每行是一个长度不超过50的字符串。
Output
对于每组输入数据,输出一行。如果输入数据是C的合法标识符,则输出"yes",否则,输出“no”。
Sample Input
3
12ajf
fi8x_a
ff  ai_2
Sample Output
no
yes
no

这道题有一定坑。
以下为正确代码。

#include <iostream>
using namespace std;

bool isValidIdentifier(const char* str) 
{
    if (!((str[0] >= 'a' && str[0] <= 'z') || (str[0] >= 'A' && str[0] <= 'Z') || str[0] == '_')) 
    {
        return false;
    }

    for (int i = 1; str[i] != '\0'; ++i) 
    {
        if (!((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= '0' && str[i] <= '9') || str[i] == '_')) 
        {
            return false;
        }
    }

    return true;
}

int main() 
{
    int n;
    cin >> n;
    cin.ignore();

    for (int i = 0; i < n; ++i) 
    {
        char str[51]; // 长度为50的字符串需要额外的一个字符存储'\0'
        cin.getline(str, 51);
        if (isValidIdentifier(str)) 
        {
            cout << "yes" << endl;
        } 
        else 
        {
            cout << "no" << endl;
        }
    }

    return 0;
}

在isvalididentifier函数中,判断的条件改为if (!((str[0] >= 'a' && str[0] <= 'z') || (str[0] >= 'A' && str[0] <= 'Z') || str[0] == '_')) 后,调试无误


2024.2.28

2030题

Problem Description
统计给定文本文件中汉字的个数。
Input
输入文件首先包含一个整数n,表示测试实例的个数,然后是n段文本。
Output
对于每一段文本,输出其中的汉字的个数,每个测试实例的输出占一行.
[Hint:]从汉字机内码的特点考虑~
Sample Input
2
WaHaHa! WaHaHa! 今年过节不说话要说只说普通话WaHaHa! WaHaHa!
马上就要期末考试了Are you ready?
Sample Output
14
9

这道题在题目中建议从汉字机内码的特点考虑,但是机内码版代码运行不通过,所以改用ASCII码进行,汉字的ASCII码为负数,且一个汉字占用两个字节,所以在输出的时候注意除以2

#include <iostream>
#include <string>
using namespace std;

int main() {
    int n;
    cin >> n;
    cin.ignore(); // 忽略换行符

    while (n--) {
        string a;
        getline(cin, a);

        int t = 0;
        for (unsigned int  i = 0; i < a.length(); ++i) {
            if (a[i] < 0) {
                t++;
            }
        }
        cout << t/2  << endl;
    }

    return 0;
}

2031题

Problem Description
输入一个十进制数N,将它转换成R进制数输出。
Input
输入数据包含多个测试实例,每个测试实例包含两个整数N(32位整数)和R(2<=R<=16, R<>10)。
Output
为每个测试实例输出转换后的数,每个输出占一行。如果R大于10,则对应的数字规则参考16进制(比如,10用A表示,等等)。
Sample Input
7 2
23 12
-4 3
Sample Output
111
1B
-11

这道题难度也不小,以下为注释版代码。

#include <iostream>
#include <cmath>
#include <string>
using namespace std;
string turn(int n,int r)
{
    string result="";
    bool negative=false;
    if(n<0)
    {
        negative=true;
        n=-n;
    }
    while (n> 0) {
        int remainder = n % r; // 求余数
        char digit; // 用于存储当前位的数字字符

        // 将余数转换为对应的字符表示
        if (remainder < 10) 
        {
            digit = remainder + '0'; // 如果余数小于10,直接使用对应的数字字符
        }
        else 
        {
            digit = remainder - 10 + 'A'; // 如果余数大于等于10,使用对应的字母表示
        }

        result = digit + result; // 将当前位的字符插入到结果字符串的最前面
        n /= r; // 更新N为除以R的结果
    }

    // 如果是负数,在结果字符串最前面添加负号
    if (negative) 
    {
        result = '-' + result;
    }

    return result;

}
int main()
{
    int n;//10进制的数字
    int r;//需要转换的进制
    while(cin>>n>>r)
    {
        cout<<turn(n,r)<<endl;
    }
    return 0;
}

2035题

Problem Description
求A^B的最后三位数表示的整数。
说明:A^B的含义是“A的B次方”
Input
输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束,不做处理。
Output
对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行。
Sample Input
2 3
12 6
6789 10000
0 0
Sample Output
8
984
1

这道题在数据较小时,使用cmath中的pow函数或者循环计算均可计算出正确结果,但是数据较大时,会造成溢出,所以需要构造一个函数,下面为示例代码。

#include <iostream>
using namespace std;

int fastPower(int a, int b) 
{
    int result = 1;
    while (b) 
    {
        if (b & 1) 
        {
            result = (result * a) % 1000;
        }
        a = (a * a) % 1000;
        b >>=1;//这里换成b=b-1不行
    }
    return result;
}

int main() 
{
    int a, b;
    while (cin >> a >> b && (a != 0 || b != 0)) 
    {
        cout << fastPower(a, b) << endl;
    }
    return 0;
}

额外注意,在函数fastPower中要使用b>>=1,b右移1,而不能单纯的b-1
在这段代码中,b >>= 1 和 b = b - 1 是两种不同的操作,分别对应着位运算的右移和数值的减法。

在 fastPower 函数中,b >>= 1 是为了将 b 向右移动一位,相当于将 b 除以2。这个操作是为了在快速幂算法中,利用指数 b 的二进制形式进行计算,以加快计算速度。

而将 b 替换为 b - 1 则是直接将 b 减去1。这样做会改变 b 的值,而不是对其进行右移操作。这对于快速幂算法是不正确的,因为快速幂算法的核心思想是利用指数 b 的二进制形式来减少乘法操作的数量,而不是简单地减小 b 的值。

因此,对于这段代码中的快速幂算法,应该保留 b >>= 1 而不是替换为 b = b - 1。

2039题

Problem Description
给定三条边,请你判断一下能不能组成一个三角形。
Input
输入数据第一行包含一个数M,接下有M行,每行一个实例,包含三个正数A,B,C。其中A,B,C <1000;
Output
对于每个测试实例,如果三条边长A,B,C能组成三角形的话,输出YES,否则NO。
Sample Input
2
1 2 3
2 2 2
Sample Output
NO
YES

这道题有坑,题目中给的是整型数据但是,一直报错,当改为double型运行通过

#include <iostream>
using namespace std;
int main()
{
    int m;
    cin>>m;
    for(int i=0;i<m;i++)
    {
        double a,b,c;//这里不要用int虽然题目中样例给的是整数
        cin>>a>>b>>c;
        if(a+b>c&&a+c>b&&b+c>a&&a>0&&a<1000&&b>0&&b<1000&&c>0&&c<1000)
        {
            cout<<"YES"<<endl;
        }
        else
        {
            cout<<"NO"<<endl;
        }
    }
    return 0;
}

2043

Problem Description
网上流传一句话:"常在网上飘啊,哪能不挨刀啊~"。其实要想能安安心心地上网其实也不难,学点安全知识就可以。
首先,我们就要设置一个安全的密码。那什么样的密码才叫安全的呢?一般来说一个比较安全的密码至少应该满足下面两个条件:
(1).密码长度大于等于8,且不要超过16。
(2).密码中的字符应该来自下面“字符类别”中四组中的至少三组。
这四个字符类别分别为:
1.大写字母:A,B,C...Z;
2.小写字母:a,b,c...z;
3.数字:0,1,2...9;
4.特殊符号:~,!,@,#,$,%,^;
给你一个密码,你的任务就是判断它是不是一个安全的密码。
Input
输入数据第一行包含一个数M,接下有M行,每行一个密码(长度最大可能为50),密码仅包括上面的四类字符。
Output
对于每个测试实例,判断这个密码是不是一个安全的密码,是的话输出YES,否则输出NO。
Sample Input
3
a1b2c3d4
Linle@ACM
^~^@^@!%
Sample Output
NO
YES
NO

这道题只需要遍历输入的字符串即可,然后看是否有三种类型的字符,或者使用cctype库中的函数也可以实现相同的效果

#include <iostream>
#include <string>

using namespace std;

bool isSafePassword(const string& password) 
{
    int length = password.length();
    // 检查密码长度是否符合要求
    if (length < 8 || length > 16) 
    {
        return false;
    }

    // 初始化四组字符类别的标志
    bool hasUpper = false, hasLower = false, hasDigit = false, hasSpecial = false;

    // 遍历密码中的每个字符,检查其所属的字符类别
    for (char ch : password) 
    {
        if (ch >= 'A' && ch <= 'Z') 
        {
            hasUpper = true;
        } 
        else if (ch >= 'a' && ch <= 'z') 
        {
            hasLower = true;
        } 
        else if (ch >= '0' && ch <= '9') 
        {
            hasDigit = true;
        } 
        else if (ch == '~' || ch == '!' || ch == '@' || ch == '#' || ch == '$' || ch == '%' || ch == '^') 
        {
            hasSpecial = true;
        }
    }

    // 检查四组字符类别的标志是否至少有三个为true
    int count = (hasUpper ? 1 : 0) + (hasLower ? 1 : 0) + (hasDigit ? 1 : 0) + (hasSpecial ? 1 : 0);
    return count >= 3;
}

int main() 
{
    int M;
    cin >> M;
    cin.ignore(); // 忽略换行符
    while (M--) 
    {
        string password;
        getline(cin, password);
        if (isSafePassword(password)) 
        {
            cout << "YES" << endl;
        } 
        else 
        {
            cout << "NO" << endl;
        }
    }
    return 0;
}

2044

Problem Description
有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行。请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数。
其中,蜂房的结构如下所示。
Input
输入数据的第一行是一个整数N,表示测试实例的个数,然后是N 行数据,每行包含两个整数a和b(0<a<b<50)。
Output
对于每个测试实例,请输出蜜蜂从蜂房a爬到蜂房b的可能路线数,每个实例的输出占一行。
Sample Input
2
1 2
3 6
Sample Output
1
3

在这里插入图片描述

这道题需要注意,在存储路径时,要使用long long型,否则会造成溢出。

#include <iostream>
using namespace std;
int main()
{
    int n;
    cin>>n;
    long long t[51];//由int改为long long结果变成了accepted,说明int型不能完全存储
    t[0]=0,t[1]=1,t[2]=2;
    for(int i=3;i<50;i++)
    {
        t[i]=t[i-1]+t[i-2];
    }
    while(n--)
    {
        int a,b;
        cin>>a>>b;
        cout<<t[b-a]<<endl;
    }
    return 0;
}

2045

有排成一行的n个方格,用红(Red)、粉(Pink)、绿(Green)三色涂每个格子,
每格涂一色,要求任何相邻的方格不能同色,且首尾两格也不同色.求全部的满足要求的涂法.
以上就是著名的RPG难题.
Input
输入数据包含多个测试实例,每个测试实例占一行,由一个整数N组成,(0<n<=50)。
Output
对于每个测试实例,请输出全部的满足要求的涂法,每个实例的输出占一行。
Sample Input
1
2
Sample Output
3
6
#include <iostream>
using namespace std;

int main() {
    int n;
    long long array[51];
    array[1] = 3;
    array[2] = 6;
    array[3] = 6;
    for (int i = 4; i < 51; i++)
        array[i] = array[i - 2] * 2 + array[i - 1];
    while (cin >> n)
        cout << array[n] << endl;
    return 0;
}

关于为什么array[i] = array[i - 2] * 2 + array[i - 1];
因为array[i-1]时,首尾不同色,且相邻不同色,所有添加一个颜色只能是一种。而当剩余两个格子未涂色时最后一个格子不能与第一个相同,那么颜色已经确定,那么倒数第二个格子有两种涂色情况。


2024.3.6

Problem Description
今年的ACM暑期集训队一共有18人,分为6支队伍。其中有一个叫做EOF的队伍,由04级的阿牛、
XC以及05级的COY组成。在共同的集训生活中,大家建立了深厚的友谊,阿牛准备做点什么来纪念这段激情燃烧的岁月,想了一想,
阿牛从家里拿来了一块上等的牛肉干,准备在上面刻下一个长度为n的只由"E" "O" "F"三种字符组成的字符串
(可以只有其中一种或两种字符,但绝对不能有其他字符),
阿牛同时禁止在串中出现O相邻的情况,他认为,"OO"看起来就像发怒的眼睛,效果不好。
你,NEW ACMer,EOF的崇拜者,能帮阿牛算一下一共有多少种满足要求的不同的字符串吗?
PS: 阿牛还有一个小秘密,就是准备把这个刻有 EOF的牛肉干,作为神秘礼物献给杭电五十周年校庆,
可以想象,当校长接过这块牛肉干的时候该有多高兴!这里,请允许我代表杭电的ACMer向阿牛表示感谢!
再次感谢!
Input
输入数据包含多个测试实例,每个测试实例占一行,由一个整数n组成,(0<n<40)。
Output
对于每个测试实例,请输出全部的满足要求的涂法,每个实例的输出占一行。
Sample Input
1
2
Sample Output
3
8
#include <iostream>
using namespace std;
int main()
{
    int n;
    long long p[40];
    p[0]=0,p[1]=3,p[2]=8;
    for(int i=3;i<40;i++)
    {
        p[i]=(p[i-1]+p[i-2])*2;//p[i-1]是以E,O,F任意一个字符结尾的可以直接添加E或F但是不能直接加O,//p[i-2]是以O结尾的只能添加E或F
    }
    while(cin>>n)
    {
        cout<<p[n]<<endl;
    }
    return 0;
}

先数出前2项所有可能组合的个数,再进行递推,发现p[i]=(p[i-1]+p[i-2])*2;p[i-1]是以E,O,F任意一个字符结尾的可以直接添加E或F但是不能直接加O,p[i-2]是以O结尾的只能添加E或F,*2即可。

2048题之前多采用斐波那契数列的思想,即当前项为前两项的和或差再进行适当的变形。

而2048题之后,则主要考虑错排思想。

简要介绍错排:首先,对于D(n),有1~n这样n个元素错排,所以对于第一个元素①,它现在可能的位置有 (n-1)个。 这是递推公式需要乘(n-1)的原因
倘若它在第k个元素的位置上,对于第k个元素而言,它所在的位置就有两种可能—第一种,它处在非第一个元素①位置上,
所以对于接下来的排列就相当于是n-1个元素的错排,即D(n-1);第二种,它处在第一个元素①的位置上,
所以在排列D(n)中有两个元素找到了位置,那么接下来的队列就相当于是n-2个元素的错排。
因此,对于D(n)都有 D(n) = (n-1) [D(n-2) + D(n-1)]

特殊地,D(1) = 0, D(2) = 1

HDU 2006'10 ACM contest的颁奖晚会隆重开始了!
为了活跃气氛,组织者举行了一个别开生面、奖品丰厚的抽奖活动,这个活动的具体要求是这样的:

首先,所有参加晚会的人员都将一张写有自己名字的字条放入抽奖箱中;
然后,待所有字条加入完毕,每人从箱中取一个字条;
最后,如果取得的字条上写的就是自己的名字,那么“恭喜你,中奖了!”
大家可以想象一下当时的气氛之热烈,毕竟中奖者的奖品是大家梦寐以求的Twins签名照呀!
不过,正如所有试图设计的喜剧往往以悲剧结尾,这次抽奖活动最后竟然没有一个人中奖!
我的神、上帝以及老天爷呀,怎么会这样呢?
不过,先不要激动,现在问题来了,你能计算一下发生这种情况的概率吗?
不会算?难道你也想以悲剧结尾?!
Input
输入数据的第一行是一个整数C,表示测试实例的个数,然后是C 行数据,每行包含一个整数n(1<n<=20),表示参加抽奖的人数。
Output
对于每个测试实例,请输出发生这种情况的百分比,每个实例的输出占一行, 结果保留两位小  数(四舍五入),具体格式请参照sample output。
Sample Input
1
2
Sample Output
50.00%
#include <iostream>
#include <iomanip>
using namespace std;

long long a[20], b[20];

int main() {
    a[0] = 0;
    a[1] = 1;
    b[0] = 1;
    b[1] = 2;
    
    for (int i = 2; i < 20; i++) {
        b[i] = (i + 1) * b[i - 1];
        a[i] = i * (a[i - 2] + a[i - 1]);
    }
    
    int n;
    cin >> n;
    while (n--) {
        int x;
        cin >> x;
        cout << fixed << setprecision(2) << a[x - 1] * 100.0 / b[x - 1] << "%" << endl;
    }
    return 0;
}

在这段代码中,数组a用于存储错排的情况数,数组b用于存储所有可能的情况。最后计算概率直接相除即可。

国庆期间,省城HZ刚刚举行了一场盛大的集体婚礼,为了使婚礼进行的丰富一些,司仪临时想出了有一个有意思的节目,叫做"考新郎",具体的操作是这样的:
首先,给每位新娘打扮得几乎一模一样,并盖上大大的红盖头随机坐成一排;
然后,让各位新郎寻找自己的新娘.每人只准找一个,并且不允许多人找一个.
最后,揭开盖头,如果找错了对象就要当众跪搓衣板...
看来做新郎也不是容易的事情...
假设一共有N对新婚夫妇,其中有M个新郎找错了新娘,求发生这种情况一共有多少种可能.
Input
输入数据的第一行是一个整数C,表示测试实例的个数,然后是C行数据,每行包含两个整数N和M(1<M<=N<=20)。
Output
对于每个测试实例,请输出一共有多少种发生这种情况的可能,每个实例的输出占一行。
Sample Input
2
2 2
3 2
Sample Output
1
3
#include<iostream>  //这道题的本质就是求解排列组合C(n,m)与错排m个元素D(m)的乘积
#include<cstdio>
using namespace std;
const int maxn = 25;
long long D[maxn], N[maxn]; /// D[i]表示错排数,N[i]表示全排列数(即n!)
int main()
{
	D[0] = 0, N[0] = 1; 
	D[1] = 0, N[1] = 1;
	D[2] = 1, N[2] = 2;//递推边界
	for (int i = 3; i < maxn; i++)
	{
		D[i] = (i - 1)*(D[i - 1] + D[i - 2]);///错排递推关系式
		N[i] = N[i - 1] * i;//求n,即所有可能的结果
	}
	int T, n, m;
	cin >> T;
	while (T--)
	{
		cin >> n >> m;
		long long a = N[n] / (N[m] * N[n - m]); ///求C(n,m)组合数   n!/(m!*(n-m)!)
		cout << D[m] * a << endl;
	}
	return 0;
}

2049题同理,不再进行赘述。

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
杭州电子科技大学ACM是指杭州电子科技大学(Hangzhou Dianzi University)学生所组成的参与国际大学生程序设计竞赛(ACM-ICPC)的团队。ACM-ICPC是全球规模最大、最具影响力的大学生程序设计竞赛,由美国计算机协会(ACM)主办。 作为杭州电子科技大学的代表,ACM团队的成员经过选拔和培训,是学校优秀的计算机科学与技术专业学生。这些学生掌握了扎实的算法和编程基础,具有丰富的解决问的能力和团队协作精神。 参加ACM竞赛对于学生们来说,不仅是锻炼自己的编程能力和算法思维,更是一个展示才华和拓宽视野的平台。比赛中,团队成员将面对各种难,需要快速思考并给出高效的解决方案,这对于他们的综合素质和实践能力是一个重要的考验。 杭州电子科技大学ACM团队在比赛中取得了优异的成绩,多次进入国际赛区的决赛,甚至获得了国际冠军头衔。这不仅彰显了团队成员的个人才华,更体现了学校培养优秀计算机人才的实力和质量。 ACM竞赛的参与不仅对于学生个人的成长和发展有积极的影响,也对学校提升学科建设和促进学院声誉有着重要的意义。杭州电子科技大学ACM团队的出色表现是学校计算机学科实力的一大体现,也是学校教育理念和教学质量的有力证明。 总的来说,杭州电子科技大学ACM是一支备受期待和骄傲的团队,他们的参赛经历和成果不仅彰显了他们个人的才华,更代表了学校在计算机科学与技术领域的卓越实力和卓越教育质量。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值