《算法笔记》codeup第三章刷题记录---入门模拟

文章目录

    • @[toc]
      • 《算法笔记》3.1小节——入门模拟->简单模拟
        • 问题 A: 剩下的树
        • 问题 B: A+B
        • 问题 C: 特殊乘法
        • 问题 D: 比较奇偶数个数
        • 问题 E: Shortest Distance (20)
        • 问题 F: A+B和C (15)
        • 问题 G: 数字分类 (20)
        • 问题 H: 部分A+B (15)
        • 问题 I: 锤子剪刀布 (20)
      • 《算法笔记》3.2小节——入门模拟->查找元素
        • 问题 A: 统计同成绩学生人数
        • 问题 B: 找x
        • 问题 C: 查找学生信息
        • 问题 D: 查找
        • 问题 E: 学生查询
      • 《算法笔记》3.3小节——入门模拟->图形输出
        • 问题 A: 输出梯形
        • 问题 B: Hello World for U
        • 问题 C: 等腰梯形
        • 问题 D: 沙漏图形 tri2str [1*+]
      • 《算法笔记》3.4小节——入门模拟->日期处理
        • 问题 A: 日期差值
        • 问题 B: Day of Week
        • 问题 C: 打印日期
        • 问题 D: 日期类
        • 问题 E: 日期累加
      • 《算法笔记》3.5小节——入门模拟->进制转换
        • 问题 A: 又一版 A+B
        • 问题 B: 数制转换
        • 问题 C: 进制转换
        • 问题 D: 八进制
      • 《算法笔记》3.6小节——入门模拟->字符串处理
        • 问题 A: 字符串连接
        • 问题 B: 首字母大写
        • 问题 C: 字符串的查找删除
        • 问题 D: 单词替换
        • 问题 E: 字符串去特定字符
        • 问题 F: 数组逆置
        • 问题 G: 比较字符串
        • 问题 H: 编排字符串
        • 问题 I: 【字符串】回文串

《算法笔记》3.1小节——入门模拟->简单模拟

链接:http://codeup.hustoj.com/contest.php?cid=100000575

问题 A: 剩下的树

​ 有一个长度为整数L(1<=L<=10000)的马路,可以想象成数轴上长度为L的一个线段,起点是坐标原点,在每个整数坐标点有一棵树,即在0,1,2,…,L共L+1个位置上有L+1棵树。
​ 现在要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)所有的树。
​ 可能有M(1<=M<=100)个区间,区间之间可能有重叠。现在要求移走所有区间的树之后剩下的树的个数。

#include
using namespace std;

int main()
{
    int l,m;
    while(cin>>l>>m)
    {
        if(l==0) break;
        else
        {
            int num[l+1]={0};
            int x1,x2;
            for(int i=0;i<m;i++)
            {
                cin>>x1>>x2;
                for(int j=x1;j<=x2;j++)
                {
                    num[j] = 1;
                }
            }
            int count = 0;
            for(int i=0;i<=l;i++)
            {
                if(!num[i]) count++;
                else continue;
            }
            cout<<count<<endl;
        }
    }
    return 0;
}
问题 B: A+B

给定两个整数A和B,其表示形式是:从个位开始,每三位数用逗号","隔开。
现在请计算A+B的结果,并以正常形式输出。

输入包含多组数据数据,每组数据占一行,由两个整数A和B组成(-10^9 < A,B < 10^9)。

请计算A+B的结果,并以正常形式输出,每组数据占一行。

#include
#include
#include
using namespace std;

long long str_to_num(char str[])
{
    int l = strlen(str);
    long long x = 0;
    for(int i=0;i<l;i++)
    {
        if(str[i]>='0' && str[i]<='9') x = x * 10 + str[i] - '0';
        else continue;
    }
    if(str[0]=='-') return -x;
    else return x;
}

int main()
{
    char str1[50], str2[50];
    while(scanf("%s %s",str1,str2)!=EOF)
    {
        long long x1=0,x2=0;
        x1 = str_to_num(str1);
        x2 = str_to_num(str2);
        cout<<x1+x2<<endl;
    }
    return 0;
}
问题 C: 特殊乘法

写个算法,对2个小于1000000000的输入,求结果。特殊乘法举例:123 * 45 = 1*4 +1*5 +2*4 +2*5 +3*4+3*5

#include
#include
#include
using namespace std;

int main()
{
    char str1[15],str2[15];
    while(scanf("%s %s",str1,str2)!=EOF)
    {
        int l1 = strlen(str1);
        int l2 = strlen(str2);
        int sum = 0;
        for(int i=0;i<l1;i++)
        {
            for(int j=0;j<l2;j++)
            {
                sum += (str1[i] - '0') * (str2[j] - '0');
            }
        }
        cout<<sum<<endl;
    }
    return 0;
}
问题 D: 比较奇偶数个数

第一行输入一个数,为n,第二行输入n个数,这n个数中,如果偶数比奇数多,输出NO,否则输出YES。

#include
#include
using namespace std;

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int x;
        int os = 0;
        int js = 0;
        for(int i=0;i<n;i++)
        {
            cin>>x;
            if(x%2==0) os++;
            else js++;
        }
        if(os>js) cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
    return 0;
}
问题 E: Shortest Distance (20)

The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits.

任务真的很简单:给定构成一个简单周期的高速公路上的N个出口,您应该说出任何一对出口之间的最短距离。

#include
#include
using namespace std;

int main()
{
    int n,x;
    cin>>n;
    int num[n+1]={0};
    int sum = 0;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        sum += x;
        num[i] = sum;
    }
    int m;
    cin>>m;
    while(m--)
    {
        int x1,x2;
        cin>>x1>>x2;
        if(x1>x2) swap(x1,x2);
        int temp = num[x2-1]-num[x1-1];
        if(temp * 2 < sum) cout<<temp<<endl;
        else cout<<sum-temp<<endl;
    }
    return 0;
}
问题 F: A+B和C (15)

给定区间[-2^31, 2^31]内的3个整数A、B和C,请判断A+B是否大于C。

#include
using namespace std;

int main()
{
    int t;
    cin>>t;
    long long a,b,c;
    for(int i=1;i<=t;i++)
    {
        cin>>a>>b>>c;
        if(a+b>c) cout<<"Case #"<<i<<": true"<<endl;
        else cout<<"Case #"<<i<<": false"<<endl;
    }
    return 0;
}
问题 G: 数字分类 (20)

给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字:

A1 = 能被5整除的数字中所有偶数的和;

A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4…;

A3 = 被5除后余2的数字的个数;

A4 = 被5除后余3的数字的平均数,精确到小数点后1位;

A5 = 被5除后余4的数字中最大数字。

每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N,随后给出N个不超过1000的待分类的正整数。数字间以空格分隔。

对给定的N个正整数,按题目要求计算A1~A5并在一行中顺序输出。数字间以空格分隔,但行末不得有多余空格。

若其中某一类数字不存在,则在相应位置输出“N”。

#include
#include
#include
using namespace std;

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int num[n];
        for(int i=0;i<n;i++)
        {
            cin>>num[i];
        }
        int cot[5] = {0};
        int coef = 1 , c1 = 0;
        double c3 = 0.0;
        for(int i=0;i<n;i++)
        {
            if(num[i] % 10 == 0) cot[0] += num[i];
            if(num[i] % 5 == 1)
            {
                cot[1] += coef * num[i];
                coef = -coef;
                c1++;
            }
            if(num[i] % 5 == 2) cot[2]++;
            if(num[i] % 5 == 3)
            {
                cot[3] += num[i];
                c3 += 1.0;
            }
            if(num[i] % 5 == 4 && num[i] > cot[4]) cot[4] = num[i];
        }
        if(cot[0]==0) cout<<"N ";
        else cout<<cot[0]<<" ";
        if(cot[1]==0 && c1==0) cout<<"N ";
        else cout<<cot[1]<<" ";
        if(cot[2]==0) cout<<"N ";
        else cout<<cot[2]<<" ";
        if(cot[3]==0) cout<<"N ";
        else cout<<fixed<<setprecision(1)<<cot[3]/c3<<" ";
        if(cot[4]==0) cout<<"N ";
        else cout<<cot[4]<<endl;
    }
    return 0;
}
问题 H: 部分A+B (15)

正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA。例如:给定A = 3862767,DA = 6,则A的“6部分”PA是66,因为A中有2个6。

现给定A、DA、B、DB,请编写程序计算PA + PB。

#include 
#include 
/* 给出字符如'6'出现n次的数字, n=1时为6 */
int charToNum(char d, int n) { 
    int numD = d - '0', res = 0;
    for (int i = 0; i < n; i++) {
        res = (res * 10 + numD);
    }
    return res;
}

int main()
{
    char a[25], b[25];
    char da, db;
    while (scanf("%s %c %s %c", a, &da, b, &db) != EOF) {
        int len1 = strlen(a), len2 = strlen(b), n1 = 0, n2 = 0;
        for (int i = 0; i < len1; i++)
            if (a[i] == da) n1++;
        for (int i = 0; i < len2; i++)
            if (b[i] == db) n2++;
        printf("%d\n", charToNum(da, n1) + charToNum(db, n2));
    }    
    return 0;
}
问题 I: 锤子剪刀布 (20)

大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示:

现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。

#include 
#include 
char c[] = {'B', 'C', 'J'};
/* 返回获胜次数最多的手势,如果解不唯一,则返回按字母序最小的手势字符 */
char checkWinWay(int m[])
{
	int k = 0;
	for (int i = 1; i < 3; i++) 
		if (m[i] > m[k]) k = i;
	return c[k];
}
int main()
{
    int N, winJ, winY, par, J[3], Y[3];
    winJ = winY = par = 0;
    memset(J, 0, sizeof(J)); // B C J
    memset(Y, 0, sizeof(Y));
    char a, b;
    scanf("%d", &N);
    getchar();        // 吸收换行 
    
    for (int i = 0; i < N; i++) {
        scanf("%c", &a);
        getchar();    // 吸收空格 
        scanf("%c", &b);
        getchar();    // 吸收换行 
        switch(a) {
            case 'C':
                switch(b) {
                    case 'C': par++; break;
                    case 'J': winJ++; J[1]++; break;
                    case 'B': winY++; Y[0]++; break;
                }
                break;
            case 'J':
                switch(b) {
                    case 'C': winY++; Y[1]++; break;
                    case 'J': par++; break;
                    case 'B': winJ++; J[2]++; break;
                }
                break;
            case 'B':
                switch(b) {
                    case 'C': winJ++; J[0]++; break;
                    case 'J': winY++; Y[2]++; break;
                    case 'B': par++; break;
                }
                break;
        }
    }
    printf("%d %d %d\n%d %d %d\n", winJ, par, N-winJ-par, winY, par, N-winY-par);
    printf("%c %c\n", checkWinWay(J), checkWinWay(Y)); 
    return 0;
}

《算法笔记》3.2小节——入门模拟->查找元素

链接:http://codeup.hustoj.com/contest.php?cid=100000576

问题 A: 统计同成绩学生人数

读入N名学生的成绩,将获得某一给定分数的学生人数输出。

测试输入包含若干测试用例,每个测试用例的格式为

第1行:N
第2行:N名学生的成绩,相邻两数字用一个空格间隔。
第3行:给定分数

当读到N=0时输入结束。其中N不超过1000,成绩分数为(包含)0到100之间的一个整数。

#include
using namespace std;

int main()
{
    int n;
    while(cin>>n)
    {
        if(n==0) break;
        else
        {
            int num[n];
            for(int i=0;i<n;i++)
            {
                cin>>num[i];
            }
            int grd;
            cin>>grd;
            int grd_cot = 0;
            for(int i=0;i<n;i++)
            {
                if(num[i]==grd) grd_cot++;
            }
            cout<<grd_cot<<endl;
        }
    }
    return 0;
}
问题 B: 找x

输入一个数n,然后输入n个数值各不相同,再输入一个值x,输出这个值在这个数组中的下标(从0开始,若不在数组中则输出-1)。

#include
#include
using namespace std;

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int num[n];
        for(int i=0;i<n;i++)
        {
            cin>>num[i];
        }
        bool flag = false;
        int dex;
        cin>>dex;
        for(int i=0;i<n;i++)
        {
            if(num[i]==dex)
            {
                cout<<i<<endl;
                flag = true;
                break;
            }
        }
        if(!flag) cout<<-1<<endl;
    }
    return 0;
}
问题 C: 查找学生信息

输入N个学生的信息,然后进行查询。

输入的第一行为N,即学生的个数(N<=1000)

接下来的N行包括N个学生的信息,信息格式如下:

01 李江 男 21

02 刘唐 男 23

03 张军 男 19

04 王娜 女 19

然后输入一个M(M<=10000),接下来会有M行,代表M次查询,每行输入一个学号,格式如下:

02

03

01

04

#include 
#include 
typedef struct student {
    char index[5];
    char name[100];
    char sex[10];
    int age;
} student;
student stu[1010];

int main() 
{
    int N;
    while (scanf("%d", &N) != EOF) {
    	for (int i = 0; i < N; i++) 
            scanf("%s %s %s %d", stu[i].index, stu[i].name, stu[i].sex, &stu[i].age);
		int M;
	    scanf("%d", &M); 
	    while (M--) {
	    	char in[10];
	        scanf("%s", in);
	        int i;
	        for (i = 0; i < N; i++) {
	        	if (strcmp(stu[i].index, in) == 0) {
	            	printf("%s %s %s %d\n", stu[i].index, stu[i].name, stu[i].sex, stu[i].age);
	            	break;
				}  
			}     
	        if (i == N) printf("No Answer!\n");
	    }
	}
    return 0;
}
问题 D: 查找

输入数组长度 n
输入数组 a[1…n]
输入查找个数m
输入查找数字b[1…m]
输出 YES or NO 查找有则YES 否则NO 。

#include 

int main()
{
    int n;
    while (scanf("%d", &n) != EOF) {
        int a[150];
        for (int i = 0; i < n; i++) 
            scanf("%d", &a[i]);
        int m;
        scanf("%d", &m);
        while (m--) {
            int num, i;
            scanf("%d", &num);
            for (i = 0; i < n; i++) 
                if (a[i] == num) {
                	printf("YES\n"); 
                	break;
				}
            if (i == n) printf("NO\n");
        }
    }
    return 0;
}
问题 E: 学生查询

输入n个学生的信息,每行包括学号、姓名、性别和年龄,每一个属性使用空格分开。最后再输入一学号,将该学号对应的学生信息输出。

测试数据有多组,第一行为样例数m。对于每个样例,第一行为学生人数n(n不超过20),加下来n行每行4个整数分别表示学号、姓名、性别和年龄,最后一行表示查询的学号。

#include 
typedef struct student {
    int index;
    char name[100];
    char sex[10];
    int age;
} student;
student stu[50];

int main() 
{
    int m;
    scanf("%d", &m);
    while (m--) {
        int n;
        scanf("%d", &n);
    	for (int i = 0; i < n; i++)  
            scanf("%d %s %s %d", &stu[i].index, stu[i].name, stu[i].sex, &stu[i].age);
        int in;
	    scanf("%d", &in);
        int i;
        for (i = 0; i < n; i++) {
        	if (stu[i].index == in) {
            	printf("%d %s %s %d\n", stu[i].index, stu[i].name, stu[i].sex, stu[i].age);
            	break;
			}  
		}     
	}
    return 0;
}

《算法笔记》3.3小节——入门模拟->图形输出

链接:http://codeup.hustoj.com/contest.php?cid=100000577

问题 A: 输出梯形

输入一个高度h,输出一个高为h,上底边为h的梯形。

#include 
int main()
{
    int h;
    while (scanf("%d", &h) != EOF) 
    {
        int UpEdge = h, DownEdge = 3 * h - 2;
        for (int i = UpEdge; i <= DownEdge; i += 2) 
        {
            int spaceNum = DownEdge - i;
            for (int j = 1; j <= spaceNum; j++)
                printf(" ");
            for (int k = 1; k <= i; k++)
                printf("*");
            printf("\n");
        }
    }
    return 0;
}
问题 B: Hello World for U

Given any string of N (>=5) characters, you are asked to form the characters into the shape of U. For example, “helloworld” can be printed as:

h d

e l

l r

lowo

That is, the characters must be printed in the original order, starting top-down from the left vertical line with n1 characters, then left to right along the bottom line with n2 characters, and finally bottom-up along the vertical line with n3 characters. And more, we would like U to be as squared as possible – that is, it must be satisfied that n1 = n3 = max { k| k <= n2 for all 3 <= n2 <= N } with n1 + n2 + n3 - 2 = N.

这一题需要解决的问题是将一个字符串写成U字形。拿到这一题的第一映像是U字的写法(可没有茴香豆的“茴”写法多),先是写第一排第一个字符,然后写第二排第一个字符……然后是最后一排,然后是倒数第二排……但在C语言中如果我们要这样写U字形的字符串就需要在数组中操作了。如果是直接输出的话,那只能自上至下一行一行输出。首先是第一行,写出第一个字符和最后一个字符,第二行写出第二个字符和倒数第二个字符……最后是最后一行。需要注意的是除了最后一行输出所有字符,前面每一行只输出两个字符。中间还有空格来隔开每行的两个字符(具体有多少空格,待会计算)。

于是问题完美解决,步骤如下:

1)计算字符串长度len;

2)计算两边的字符数side=(len+2)/3;

3)计算最后一行中间的字符数(前面每行中间的空格数);

4)输出每行相应的字符。

#include 
#include 
int main()
{
    char s[100];
    int side, mid, len;
    while (scanf("%s", s) != EOF) 
    {
        len = strlen(s);
        side = (len + 2) / 3;
        mid = len - side * 2;
        for (int i = 0; i < side; i++) 
        {
            if (i < side - 1) 
            { //输出除最后一行的前面所有行
                printf("%c", s[i]);
                for (int j = 0; j < mid; j++)
                    printf(" ");
                printf("%c\n", s[len - 1 - i]);
            } 
            else if (i == side - 1) 
            { //输出最后一行
                for (int j = 0; j < mid + 2; j++) 
                    printf("%c", s[i++]);
                printf("\n");
            }
        }
    }
    return 0;
}
问题 C: 等腰梯形

请输入高度h,输入一个高为h,上底边长为h 的等腰梯形(例如h=4,图形如下)。

#include 
int main()
{
    int m, h;
    scanf("%d", &m);
    while (m--) 
    {
        scanf("%d", &h);
        int UpEdge = h, DownEdge = 3 * h - 2;
        for (int i = UpEdge; i <= DownEdge; i += 2) 
        {
            //打印空格
            int spaceNum = (DownEdge - i) / 2;
            for (int j = 0; j < spaceNum; j++)
                printf(" ");
            //打印等腰梯形主体
            for (int k = 0; k < i; k++)
                printf("%c", '*');
            printf("\n");
        }
    }
    return 0;
}
问题 D: 沙漏图形 tri2str [1*+]

问题:输入n,输出正倒n层星号三角形。首行顶格,星号间有一空格,效果见样例

#include 

int main()
{
    int n;
    while (scanf("%d", &n) != EOF) 
    {
        //打印上半部分 
        int UpEdge = n + n - 1; //第一层的字符数(包括空格和星号)
        for (int i = UpEdge; i >= n; i--) 
        { //i表示每层所拥有的字符数
            int spaceNum = UpEdge - i;
            for (int j = 0; j < spaceNum; j++)
                printf(" ");
            int charNum = i - n + 1;
            for (int j = 0; j < charNum - 1; j++) 
                printf("* ");
            printf("*\n");
        }
        //打印下半部分 
        for (int i = n + 1; i <= UpEdge; i++) 
        {
            int spaceNum = UpEdge - i;
            for (int j = 0; j < spaceNum; j++)
                printf(" ");
            int charNum = i - n + 1;
            for (int j = 0; j < charNum - 1; j++) 
                printf("* ");
            printf("*\n");
        }
    }
    return 0;
}

《算法笔记》3.4小节——入门模拟->日期处理

链接:http://codeup.hustoj.com/contest.php?cid=100000578

问题 A: 日期差值

有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。

#include 
int month[13][2] = 
{ //平年闰年的每个月天数(月/日), 第一行平年, 第二行闰年
    {0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31},
    {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31} // {0, 0}没有意义
};
bool isLeap(int year) 
{ //判断是否是闰年
    return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

int main()
{
    int time1, y1, m1, d1;
    int time2, y2, m2, d2;
    while (scanf("%d%d", &time1, &time2) != EOF) 
    { //scanf(%d)会忽视空格和换行 
        if (time1 > time2) 
        { //如果time1晚于time2则交换, 使第一个日期早于第二个日期
            int temp = time1;
            time1 = time2;
            time2 = temp;
        }
        y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100;
        y2 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100;
        int ans = 1; //记录日期差值, 因为连续两个日期天数为两天, 所以初值为1
        /* 第一个日期没有达到第二个日期时循环 */
        while (y1 < y2 || m1 < m2 || d1 < d2) 
        {
            d1++;
            if (d1 == month[m1][isLeap(y1)] + 1) 
            { //满当月天数
                d1 = 1;  //日期变为下个月的1号
                m1++;    //月份+1
            }
            if (m1 == 13) 
            { //月份满12个月
                m1 = 1;  //月份变为下一年的1月
                y1++;    //年+1
            }
            ans++; //累计 
        }
        printf("%d\n", ans);
    }
    return 0;
}
问题 B: Day of Week

We now use the Gregorian style of dating in Russia. The leap years are years with number divisible by 4 but not divisible by 100, or divisible by 400.
For example, years 2004, 2180 and 2400 are leap. Years 2004, 2181 and 2300 are not leap.
Your task is to write a program which will compute the day of week corresponding to a given date in the nearest past or in the future using today’s agreement about dating.

#include 
#include 
struct Date 
{
	int y, m, d;
};
char MonthName[13][12]= {"None", "January", "February", "March", "April", "May", 
   "June", "July", "August", "September", "October", "November", "December"};
char Weekday[8][12] = {"None", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday"};
int month[13][2] = { //平年闰年的每个月天数(月/日), 第一行平年, 第二行闰年
    {0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31},
    {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31} // {0, 0}没有意义
};

int mapMonth(char s[]) 
{
    for (int i = 1; i < 13; i++) 
    {
    	if (strcmp(s, MonthName[i]) == 0) 
           return i;
	}
    return 0;
}

bool isLeap(int year) 
{ //判断是否是闰年
    return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

int sumDays(struct Date tmp) 
{
	int day = 0;
	for (int i = 0; i < tmp.y; i++) 
    {
		day += (isLeap(i) ? 366 : 365);
	}
    for (int i = 1; i < tmp.m; i++) 
    {
    	day += month[i][isLeap(tmp.y)];
	}
	for (int i = 1; i < tmp.d; i++) 
    {
		day++;
	}
	return day; // 737634
}

int main() 
{
    struct Date MyDay; // now = {2019, 7, 29}; 距离公元元年737634天 
    char mEnglish[14];
    while (scanf("%d%s%d", &MyDay.d, mEnglish, &MyDay.y) != EOF) 
    {
        MyDay.m = mapMonth(mEnglish);
        int dayCount = sumDays(MyDay) - 737634; //得到日期差值
	 	int offset = ((dayCount % 7) + 7) % 7;  //对负数和超出的正数修正 
	 	printf("%s\n", Weekday[1 + offset]); //1-7 20190729星期一
    }
    return 0;
}
问题 C: 打印日期

给出年分m和一年中的第n天,算出第n天是几月几号。

#include 
int month[13][2] = { //平年闰年的每个月天数(月/日), 第一行平年, 第二行闰年
    {0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31},
    {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31} // {0, 0}没有意义
};
bool isLeap(int year) 
{ //判断是否是闰年
    return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

int main()
{
    int year, day;
    while (scanf("%d%d", &year, &day) != EOF) 
    {
        int y = year, m = 1, d = 1, cnt = 1; //cnt计数, 表示第几天

        while (cnt < day) 
        {
            d++;
            if (d == month[m][isLeap(y)] + 1) 
            {
                m++;
                d = 1;
            }
            cnt++; 
        }
        printf("%04d-%02d-%02d\n", y, m, d);
    }
    return 0;
}
问题 D: 日期类

编写一个日期类,要求按xxxx-xx-xx 的格式输出日期,实现加一天的操作。

#include 
int month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int main()
{
    int M;
    scanf("%d", &M);
    int y, m, d;
    for (int i = 0; i < M; i++) 
    {
        scanf("%d%d%d", &y, &m, &d);
        d++;
        if (d == month[m] + 1) 
        {
            m++;
            d = 1;
        }
        printf("%04d-%02d-%02d\n", y, m, d);
    }
    return 0;
}
问题 E: 日期累加

设计一个程序能计算一个日期加上若干天后是什么日期。

#include 
int month[13][2] = { //平年闰年的每个月天数(月/日), 第一行平年, 第二行闰年
    {0, 0}, {31, 31}, {28, 29}, {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31},
    {31, 31}, {30, 30}, {31, 31}, {30, 30}, {31, 31} // {0, 0}没有意义
};
bool isLeap(int year) 
{ //判断是否是闰年
    return (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
}

int main() 
{
    int M;
    scanf("%d", &M);
    int y, m, d, days;
    while (M--) 
    {
        scanf("%d %d %d %d", &y, &m, &d, &days);
        int cnt = 0; //表示已增加的天数, 与days比较做循环
        while (cnt < days) 
        {
            d++;
            if (d == month[m][isLeap(y)] + 1) 
            {
                m++;
                d = 1;
            }
            if (m == 13) 
            {
                y++;
                m = 1;
            }
            cnt++;
        }
        printf("%04d-%02d-%02d\n", y, m, d);
    }
    return 0;
} 

《算法笔记》3.5小节——入门模拟->进制转换

链接:http://codeup.hustoj.com/contest.php?cid=100000579

问题 A: 又一版 A+B

输入两个不超过整型定义的非负10进制整数A和B(<=2^31-1),输出A+B的m (1 < m <10)进制数。

#include 

int main() 
{
    long long a, b, sum;
    int m, nums[50];
    while (scanf("%d", &m), m) 
    {
        scanf("%lld%lld", &a, &b);
        sum = a + b;
        int i = 0;
        //10进制转换为R进制的代码
        do {
            nums[i++] = sum % m;
            sum /= m;
        } while (sum != 0);
        //倒着打印
        for (int j = i - 1; j >= 0; j--) {
            
            printf("%d", nums[j]);
            if (j == 0) printf("\n");
        }
    }
    return 0;
}
问题 B: 数制转换

求任意两个不同进制非负整数的转换(2进制~16进制),所给整数在long所能表达的范围之内。
不同进制的表示符号为(0,1,…,9,a,b,…,f)或者(0,1,…,9,A,B,…,F)。

#include 
#include 

int CharToOct(int a, char n[]) 
{  //按进制a将n字符串(可表示2-16进制)转换为10进制数
    int sum = 0, product = 1;
    for (int i = strlen(n) - 1; i >= 0; i--) {
        if (n[i] <= '9') sum += (n[i] - '0') * product;
        else if (n[i] <= 'F') sum += (n[i] - 'A' + 10) * product; //大写字母符号
        else if (n[i] <= 'f') sum += (n[i] - 'a' + 10) * product; //小写字母符号
        product *= a;
    }
    return sum;
}

void OctToChar(int temp, int b, char r[]) 
{ //将10进制数按b进制转换成r字符串
    int i = 0;
    do {
        int k = temp % b;
        if (k <= 9) r[i++] = '0' + k; //十进制符号
        else r[i++] = 'A' + k - 10;   //用大写字母表示大于9的数字
        temp /= b;
    } while (temp != 0);
    r[i] = '\0';  //必须添加结束符, 不然strlen无法正确判别长度 
}

int main() 
{
    int a, b; // 2-16
    char n[100];
    while (scanf("%d%s%d", &a, n, &b) != EOF) 
    {
        int temp = CharToOct(a, n);
        if (b == 10) 
        {
        	printf("%d\n", temp);
        	continue;
		}
		char r[100];
        OctToChar(temp, b, r);
        
        for (int j = strlen(r) - 1; j >= 0; j--) 
            printf("%c", r[j]);
        printf("\n");
    }
    return 0;
}
问题 C: 进制转换

将一个长度最多为30位数字的十进制非负整数转换为二进制数输出。

多组数据,每行为一个长度不超过30位的十进制非负整数。
(注意是10进制数字的个数可能有30个,而非30bits的整数)

#include 

int main() 
{
    char s[32]; //将十进制字符串转换为倒排的二进制字符串, 需模拟多次数字取余和除法
    while (gets(s)) 
    {
        char nums[100] = {};
        int numsSize = 0, sum = 1; //全十进制字符串
        while (sum) 
        { //当十进制字符还未除完时继续循环
            sum = 0; //每一次十进制字符串除以2都恢复0
            for (int i = 0; s[i]; i++) 
            {
                int digit = s[i] - '0';
                int x = digit / 2; 
                sum += x;
                if (s[i + 1]) 
                {
                    s[i + 1] += (digit % 2 * 10);
                } 
                else
                {
                    nums[numsSize++] = digit % 2 + '0'; //从低位向高位存入取余的字符
                }
                s[i] = x + '0'; //一位字符的变化
            }
        }
        for (int k = numsSize - 1; k >= 0; k--) 
        {
            printf("%c", nums[k]);
        }
        printf("\n");
    }
    return 0;
}
问题 D: 八进制

输入一个整数,将其转换成八进制数输出。

#include 

int main() 
{
    int N, nums[50];
    while (scanf("%d", &N) != EOF) 
    {
        int i = 0;
        do {
            nums[i++] = N % 8;
            N /= 8;
        } while (N != 0);
        for (int j = i - 1; j >= 0; j--) 
            printf("%d", nums[j]);
        printf("\n");
    }
    return 0;
}

《算法笔记》3.6小节——入门模拟->字符串处理

链接:http://codeup.hustoj.com/contest.php?cid=100000580

问题 A: 字符串连接

不借用任何字符串库函数实现无冗余地接受两个字符串,然后把它们无冗余的连接起来。

#include 

int main() 
{
    char s1[200], s2[100], r[210];
    while (scanf("%s%s", s1, s2) != EOF) 
    {
        int i;
        for (i = 0; s1[i]; i++) 
        {
            r[i] = s1[i];
        }
        for (int j = 0; s2[j]; j++) 
        {
            r[i++] = s2[j];
        }
        r[i] = '\0';
        puts(r);
    }
    return 0;
}
问题 B: 首字母大写

对一个字符串中的所有单词,如果单词的首字母不是大写字母,则把单词的首字母变成大写字母。
在字符串中,单词之间通过空白符分隔,空白符包括:空格(’ ‘)、制表符(’\t’)、回车符(’\r’)、换行符(’\n’)。

#include 

int main() 
{
    char s[120];
    while (gets(s) != NULL)
    {
        for (int i = 0; s[i]; i++) 
        {
            if (
			   ((!i) || (s[i-1] == ' ' || s[i-1] == '\t' || s[i-1] == '\r' || s[i-1] == '\n'))
			    && s[i] >= 'a' && s[i] <= 'z'
	        ) 
                s[i] -= ('a' - 'A'); // s[i] - 32
        }
        puts(s);
    }
    return 0;
}
问题 C: 字符串的查找删除

给定一个短字符串(不含空格),再给定若干字符串,在这些字符串中删除所含有的短字符串。

#include 

char del[1000], temp[1001][1001], ans[1001][1001];

int main() 
{
    int index = 0;
    gets(del);
    for (; gets(temp[index]) != NULL; index++);  //读入数据
    //将要删除的字符转为小写
    for (int i = 0; del[i]; i++) 
    {
        if (del[i] >= 'A' && del[i] <= 'Z') 
        {
            del[i] += 32; 
        }
    }
    for (int i = 0; i < index; i++) 
    {
        int k;
        //用另一二维数组存储原数据,然后将原数据转化为小写字母
        for (k = 0; temp[i][k]; k++) 
        {
            ans[i][k] = temp[i][k];
            if (temp[i][k] >= 'A' && temp[i][k] <= 'Z') 
            {
                temp[i][k] += 32;
            }
        }
        ans[i][k] = '\0'; //结束一句的复制
        //进行短字符判断,如果不是短字符或空格就输出
        for (int j = 0, len = 0; temp[i][j]; j++, len = 0) 
        { //用len加以试探 
            while (temp[i][j + len] == del[len]) 
            { //判断是否与短字符第一个字符相同, 相同则继续循环
                len++;
                if (!del[len]) 
                { //这一段与短字符完全相同
                    j += len;    //指向i行j列的指针跳过这一段
                    len = 0;     //接着循环比较, 不同则进入下面的if语句打印字符
                }
            }
            if (temp[i][j] != ' ')  printf("%c", ans[i][j]);
        }
        printf("\n");  //输出一句后的换行
    }
    return 0;
}
问题 D: 单词替换

输入一个字符串,以回车结束(字符串长度<=100)。该字符串由若干个单词组成,单词之间用一个空格隔开,所有单词区分大小写。现需要将其中的某个单词替换成另一个单词,并输出替换之后的字符串。

#include 
#include 

int main() 
{
    char s[120];
    while (gets(s)) 
    {
        char source[110] = {}, dest[110] = {}, words[110][50] = {};
        gets(source);
        gets(dest);
        int r = 0, c = 0; 
        for (int i = 0; s[i]; i++) 
        {
            if (s[i] != ' ') 
            {
                words[r][c++] = s[i];
            } 
            else 
            {
                words[r++][c] = '\0';
                c = 0;
            }
        }
        for (int j = 0; j <= r; j++) 
        {
            if (strcmp(words[j], source) == 0) 
            {
                printf("%s", dest);
            } 
            else 
            {
                printf("%s", words[j]);
            }
            if (j < r) printf(" ");
            else printf("\n");
        }
    }
    return 0;
}
问题 E: 字符串去特定字符

输入字符串s和字符c,要求去掉s中所有的c字符,并输出结果。

#include 

int main() 
{
    char s[1000], c; 
    
    while (gets(s) != NULL) 
    {
        c = getchar();
        for (int i = 0; s[i]; i++) 
            if (s[i] != c) printf("%c", s[i]);
        printf("\n");
        getchar();
    }
    return 0;
}
问题 F: 数组逆置

输入一个字符串,长度小于等于200,然后将数组逆置输出。

#include 
#include 

int main() 
{
    char s[210];
    while (gets(s) != NULL) 
    { //可能有空格
        for (int i = strlen(s) - 1; i >= 0; i--) 
            printf("%c", s[i]);
        printf("\n");
    }
    return 0;
}
问题 G: 比较字符串

输入两个字符串,比较两字符串的长度大小关系。

#include 

int main() 
{
    char s[100], r[100];
    int m;
    scanf("%d", &m);
    while (m--) 
    {
        scanf("%s%s", s, r);
        int slen = 0, rlen = 0;
        for (slen = 0; s[slen]; slen++);
        for (rlen = 0; r[rlen]; rlen++);
        if (slen == rlen) 
        {
            printf("%s is equal long to %s\n", s, r);
        } 
        else if (slen > rlen) 
        {
            printf("%s is longer than %s\n", s, r);
        } 
        else 
        {
            printf("%s is shorter than %s\n", s, r);
        }
    }
}

问题 H: 编排字符串

请输入字符串,最多输入4 个字符串,要求后输入的字符串排在前面,例如

输入:EricZ

输出:1=EricZ

输入:David

输出:1=David 2=EricZ

输入:Peter

输出:1=Peter 2=David 3=EricZ

输入:Alan

输出:1=Alan 2=Peter 3=David 4=EricZ

输入:Jane

输出:1=Jane 2=Alan 3=Peter 4=David

#include 
#include  

int main() 
{
    int m;
    scanf("%d", &m);
    char s[5][35]; //使用1-4行 
    for (int i = 1; i <= m; i++) 
    {
        int j, w = i >= 1 && i <= 4 ? i : 4; //获得字符串数目
        for (j = w; j > 1; j--) 
        { //将旧的字符串移到下一个位置
            strcpy(s[j], s[j - 1]);
  		}
        scanf("%s", s[1]);  //永远在第一个位置存入新字符串
        for (int k = 1; k <= w; k++) 
        { //按格式打印全部已存入的字符串
            if (k < w) printf("%d=%s ", k, s[k]); 
			else  printf("%d=%s\n", k, s[k]);
        }
    }
   return 0;
}
问题 I: 【字符串】回文串

读入一串字符,判断是否是回文串。“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。

#include 
#include 

int main() 
{
    char s[260];
    while (gets(s) != NULL) 
    {
        int left = 0, right = strlen(s) - 1, flag = 1;
        for (int i = left, j = right; i < j; i++, j--) 
        { //双指针滑动
            if (s[i] != s[j]) 
            {
                printf("NO\n");
                flag = 0;
                break;
            }
        }
        if (flag) printf("YES\n");
    }
    return 0;
}

你可能感兴趣的:(算法笔记,算法笔记,入门模拟,codeup)