ACM实训冲刺第二天

目录

今日学习计划

复习回顾

SUM Problem

A+B problem

蓝桥杯ACM算法竞赛辅导

九宫幻方

问题

思路

代码

罗马数字的枚举法

问题

思路

代码

 利用位数猜年龄

问题

思路

代码(用java比较简单)

罗马数字逆向解法

问题

思路

代码

第1套题

 Anton and Letters

问题

思路

代码

Sum of Digits

问题

思路

Sum of Digits / Digital Root - 数字和/数字根_sum of the digits-CSDN博客

代码


今日学习计划

1.复习回顾

2.习题Anton and Letters、Sum of Digits

3.看蓝桥杯ACM算法竞赛辅导第1讲(九宫幻方解法、罗马数字的枚举解法、猜年龄利用位数信息、罗马数字逆向解法)


复习回顾

1.输入输出 scanf("%d",&a); printf("%d",a);

2.基本运算 ++a a++

3.循环语句 while(条件){ } for(int i = 0; n>=0; i++){ }

4.条件分支if( ){ }else if{ }else{ }

5.函数 返回值是要传给main 函数事先要声明

6.数组

SUM Problem

#include<stdio.h>
int main(){
	//声明变量
	int n,sum;
	while(scanf("%d",&n)!=EOF){
		if(n%2==0){ //【注意】是%而不是/
			sum=n/2*(n+1);
		}else{
			sum=(n+1)/2*n;
		}
		printf("%d",sum);
	}	
	
	return 0;
}

A+B problem

1.读取测试用例T

2.声明变量

3.循环读取每组测试用例

4.读取整数number

5.初始化sum置0

6.算出number长度

7.从低到高计算,需要把字符串转为数字,加和为10

8.按格式输出

# include <stdio.h>
# include <string.h>//需要注意 
int main() {
	int T;
	scanf("%d",&T);
	int j,k;
	for(int j=1;j<=T;j++){
		char number1[1000];
		char number2[1000];
		int sum[1000]={0};//易错点 
		//读取用例number
		scanf("%s%s",&number1,&number2) ;
		int len1=strlen(number1);
		int len2=strlen(number2);
		int i;
		for(i=0;i<len1||i<len2;i++){
			if(i<len1)
				sum[i]+=number1[len1-i-1]-'0';//转换成字符串
			if(i<len2) 
				sum[i]+=number2[len2-i-1]-'0';
			if(sum[i]>=10){
				sum[i+1]=sum[i]/10;
				sum[i]=sum[i]%10;
			}
		}
		//格式输出
		printf("Case %d:\n",j) ;
		for(k=0;k<len1;k++)
			printf("%c",number1[k]);
		printf(" ");
		printf("+");
		printf(" ");
		for(k=0;k<len2;k++)
			printf("%c",number2[k]);
		printf(" ");
		printf("=");
		printf(" ");
		if(len1<len2);
			len1=len2;
		if(sum[i]>0)
			printf("%d",sum[i]);
		for (i = len1 - 1; i >= 0; i--)
			printf("%d", sum[i]);
		printf("\n\n");

	}
	
	
	
	
	return 0;
}

蓝桥杯ACM算法竞赛辅导

九宫幻方

问题

小明最近在教邻居家的小朋友小学奥数,而最近正好讲述到了三阶幻方这个部分,三阶幻方指的是将 1∼9 不重复的填入一个 3×3 的矩阵当中,使得每一行、每一列和每一条对角线的和都是相同的。

三阶幻方又被称作九宫格,在小学奥数里有一句非常有名的口诀:“二四为肩,六八为足,左三右七,戴九履一,五居其中”,通过这样的一句口诀就能够非常完美的构造出一个九宫格来。

4 9 2

3 5 7

8 1 6

有意思的是,所有的三阶幻方,都可以通过这样一个九宫格进行若干镜像和旋转操作之后得到。

现在小明准备将一个三阶幻方(不一定是上图中的那个)中的一些数抹掉,交给邻居家的小朋友来进行还原,并且希望她能够判断出究竟是不是只有一个解。

而你呢,也被小明交付了同样的任务,但是不同的是,你需要写一个程序~

输入格式:

一个 3×3 的矩阵,其中为 0 的部分表示被小明抹去的部分。数据保证给出的矩阵至少能还原出一组可行的三阶幻方。

输出格式:

如果仅能还原出一组可行的三阶幻方,则将其输出,否则输出 "Too Many"。

输入样例

0 7 2
0 5 0
0 3 0
输出样例:

6 7 2
1 5 9
8 3 4

思路

枚举出所有情况:直接找出幻方的所有可能,旋转和镜像产生的可能,总共8总,顺时针旋转4次,镜像之后顺时针旋转4次

 {4, 9, 2, 3, 5, 7, 8, 1, 6},
 {8, 3, 4, 1, 5, 9, 6, 7, 2},
 {6, 1, 8, 7, 5, 3, 2, 9, 4},
 {2, 7, 6, 9, 5, 1, 4, 3, 8},
 {2, 9, 4, 7, 5, 3, 6, 1, 8},
 {6, 7, 2, 1, 5, 9, 8, 3, 4},
 {8, 1, 6, 3, 5, 7, 4, 9, 2},
 {4, 3, 8, 9, 5, 1, 2, 7, 6},

char p[8][10]={           //枚举九宫幻方的所有可能
		         {"492357816"},
		         {"438951276"},
		         {"294753618"},
		         {"276951438"},
		         {"672159834"},
		         {"618753294"},
		         {"834159672"},
		         {"816357492"}
};

再将输入的不为0的数与之对比。

for(i=0;i<8;i++)
	{
		if(test(s,p[i]))
		{
			printf("\n");
			flag=0;
			for(j=0;j<9;j++)
			{
				printf("%c ",p[i][j]); 
				if((j+1)%3==0)
				{
					printf("\n");
				}
			}
			
		}
	}

代码

#include<stdio.h>

//test函数,进行匹配
int test(char s[],char p[])
{
	int i;
	for(i=0;i<9;i++)
	{
		if(s[i]=='0')
		continue;
		if(s[i]==p[i])
		continue;
		return 0;
	}
	return 1;
}

int main()
{
	int i,j,flag=1;
	char s[9];
    //输入魔方缺失部分
	for(i=0;i<9;i++)
	{
		int num;
		scanf("%d",&num);
		s[i]='0'+num;
	}
	char p[8][10]={           
    //枚举九宫幻方的所有可能
		         {"492357816"},
		         {"438951276"},
		         {"294753618"},
		         {"276951438"},
		         {"672159834"},
		         {"618753294"},
		         {"834159672"},
		         {"816357492"}
    };
	
    //核心代码部分
	for(i=0;i<8;i++)
	{
		if(test(s,p[i]))
		{
			printf("\n");
			flag=0;
			for(j=0;j<9;j++)
			{
				printf("%c ",p[i][j]); 
				if((j+1)%3==0)
				{
					printf("\n");
				}
			}
			
		}
	}
	
	if(flag)
	{
		printf("Too Many");
	}
	
	return 0;         
} 

罗马数字的枚举法

问题

古罗马帝国开创了辉煌的人类文明,但他们的数字表示法的确有些繁琐,尤其在表示大数的时候,现在看起来简直不能忍受,所以在现代很少使用了。
之所以这样,不是因为发明表示法的人的智力的问题,而是因为一个宗教的原因,当时的宗教禁止在数字中出现0的概念!
罗马数字的表示主要依赖以下几个基本符号:


I --> 1
V --> 5
X --> 10
L --> 50
C --> 100
D --> 500
M --> 1000


这里,我们只介绍一下1000以内的数字的表示法。
单个符号重复多少次,就表示多少倍。最多重复3次。
比如:CCC表示300  XX表示20,但150并不用LLL表示,这个规则仅适用于I X C M。
如果相邻级别的大单位在右,小单位在左,表示大单位中扣除小单位。
比如:IX表示9  IV表示4  XL表示40 
49 = XLIX

思路

枚举出所有情况,在原始基础上加对应的数字;列出所有相邻数字情况,并进行补偿

代码

#include<stdio.h>
#include<string.h>
 
char numString[ 10 ];


// 罗马数字的枚举解法
int main()
{
     gets(numString);//获取字符串
     int i,num=0;
     for(i = 0 ; i < 9 ; i ++)
     {
         if(numString[ i ] == 'I')num += 1;
         if(numString[ i ] == 'V')num += 5;
         if(numString[ i ] == 'X')num += 10;
         if(numString[ i ] == 'L')num += 50;
         if(numString[ i ] == 'C')num += 100;
         if(numString[ i ] == 'D')num += 500;
         if(numString[ i ] == 'M')num += 1000;
     }
     //补偿
     if(strstr(numString,"IV"))num -=2;
     if(strstr(numString,"IX"))num -=2;
     if(strstr(numString,"XL"))num -=20;
     if(strstr(numString,"XC"))num -=20;
     if(strstr(numString,"CD"))num -=200;
     if(strstr(numString,"CM"))num -=200;

     printf("%d\n",num);
     return 0;
}

 利用位数猜年龄

问题

美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学。他曾在1935~1936年应邀来中国清华大学讲学。一次,他参加某个重要会议,年轻的脸孔引人注目。于是有人询问他的年龄,他回答说:“我年龄的立方是个4位数。我年龄的4次方是个6位数。这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次。”请你推算一下,他当时到底有多年轻。

思路

通过for循环暴力破解。

代码(用java比较简单)

结果

 显然是18岁

罗马数字逆向解法

问题

输入一个1到4000不包含4000的整数转换成罗马数字

思路

输入一个1到4000不包含4000的整数,将其转换成罗马数字

罗马数字规则:
            I(1)、V(5)、X(10)、L(50)、C(100)、D(500)、 M(1000))

但特殊的是,每一位的四和九是特殊的:

4:IV   9: IX  40: XL 90: XC  400:  CD  900 : CM 

不难发现其实就是后面的减去前面的

然后通过

        num / 1000;
        num % 1000  / 100;
        num  % 100 / 10;
        num /1000;

分别求出千位,百位,十位,个位的数。

最后通过枚举得出结论

代码

#include <stdio.h>

char* RomanNum(int num) {
    if (0 < num && num < 4000) {
        static char s[16]; // 静态数组,用于存储结果字符串
        int m = num / 1000;
        int c = num % 1000 / 100;
        int x = num % 100 / 10;
        int a = num % 10;
        int index = 0; // 用于记录字符串的位置

        if (m == 1) s[index++] = 'M';
        else if (m == 2) {s[index++] = 'M'; s[index++] = 'M';}
        else if (m == 3) {s[index++] = 'M'; s[index++] = 'M'; s[index++] = 'M';}

        if (c == 1) s[index++] = 'C';
        else if (c == 2) {s[index++] = 'C'; s[index++] = 'C';}
        else if (c == 3) {s[index++] = 'C'; s[index++] = 'C'; s[index++] = 'C';}
        else if (c == 4) {s[index++] = 'C'; s[index++] = 'D';}
        else if (c == 5) s[index++] = 'D';
        else if (c == 6) {s[index++] = 'D'; s[index++] = 'C';}
        else if (c == 7) {s[index++] = 'D'; s[index++] = 'C'; s[index++] = 'C';}
        else if (c == 8) {s[index++] = 'D'; s[index++] = 'C'; s[index++] = 'C'; s[index++] = 'C';}
        else if (c == 9) {s[index++] = 'C'; s[index++] = 'M';}

        if (x == 1) s[index++] = 'X';
        else if (x == 2) {s[index++] = 'X'; s[index++] = 'X';}
        else if (x == 3) {s[index++] = 'X'; s[index++] = 'X'; s[index++] = 'X';}
        else if (x == 4) {s[index++] = 'X'; s[index++] = 'L';}
        else if (x == 5) s[index++] = 'L';
        else if (x == 6) {s[index++] = 'L'; s[index++] = 'X';}
        else if (x == 7) {s[index++] = 'L'; s[index++] = 'X'; s[index++] = 'X';}
        else if (x == 8) {s[index++] = 'L'; s[index++] = 'X'; s[index++] = 'X'; s[index++] = 'X';}
        else if (x == 9) {s[index++] = 'X'; s[index++] = 'C';}

        if (a == 1) s[index++] = 'I';
        else if (a == 2) {s[index++] = 'I'; s[index++] = 'I';}
        else if (a == 3) {s[index++] = 'I'; s[index++] = 'I'; s[index++] = 'I';}
        else if (a == 4) {s[index++] = 'I'; s[index++] = 'V';}
        else if (a == 5) s[index++] = 'V';
        else if (a == 6) {s[index++] = 'V'; s[index++] = 'I';}
        else if (a == 7) {s[index++] = 'V'; s[index++] = 'I'; s[index++] = 'I';}
        else if (a == 8) {s[index++] = 'V'; s[index++] = 'I'; s[index++] = 'I'; s[index++] = 'I';}
        else if (a == 9) {s[index++] = 'I'; s[index++] = 'X';}

        s[index] = '\0'; // 结束字符串
        return s;
    }
    return "输入范围有误";
}

int main() {
    int num;
    printf("请输入一个[1——4000)的整数: ");
    scanf("%d", &num);
    printf("%s\n", RomanNum(num));
    return 0;
}

第1套题

 Anton and Letters

问题

给出一个字符集合,请你判断出现的不同字符个数

学弟:天啊,这次的题面也太简洁了,爱了爱了

学长:编题面实在是太累了

Input

        输入一行,长度在1000以内

        仅包括小写字母、‘{’、‘}’ 和空格

Output

   输出一行,表示出现的不同字母个数

思路

打印一个数字——Anton 集合中不同字母的数量 

代码

# include<stdio.h>
int main(){
    int flags[26];
    for(int i = 0; i < 26; i++) flag[i]=0;
    char temp;
    scanf("%c",&temp);//输入
    while(temp!='}'){
        scanf("%c",&temp);
        if(temp=='}')break;
        if(temp<'z'&&temp>='a'){
            flag[temp-'a']++;
        }
    }
    int cnt =0 ;
    for(int i =0;i<26;i++){
        if(flag[i]>0) cnt++;
    }
    printf("%d",cnt);
}
    

Sum of Digits

问题

在看完最后一部哈利波特电影后,小杰拉尔德也决定练习魔法。他在父亲的魔法书里发现了一个咒语,可以把任何数字变成数字的总和。就在杰拉尔德知道这一点的那一刻,他遇到了一个数字n。杰拉尔德可以对它施多少次咒语,直到这个数字变成一位数?

输入
第一行包含唯一的整数n(0≤n≤10100000)。它保证n不包含任何前导零。

输出
输出一个数字可以被其数字之和替换的次数,直到它只包含一个数字。

在第一个样本中,数字已经是一位数-先驱不能施法。

第二个测试包含数字10。施放一次法术后,它就变成了1,这个过程就完成了。因此,杰拉德只能施一次咒语。

第三个测试包含编号991。当一个人施咒时,会发生以下变化:991→19→10→1。经过三次变换,这个数字变成了一位数。

思路

可参考视频 编程学习

Sum of Digits / Digital Root - 数字和/数字根_sum of the digits-CSDN博客

代码

#include<stdio.h>
#includ<stdlib.h>
#include<string.h>
char s[100000]
int i = 0;
int result = 0;
int sum = 0;
int main(){
    scanf("%s",s);
    while(1){
        if(strlen(s)==1) 
            break;
        sum=0;
        for(i=0;i < strlen(s); i++){
            sum+=s[i]-'0';
        }
        itoa(sum ,s ,10);
        result++;
    }
    printf("%d",result);
    return 0;
}

今天下午着重学习Antion and Letters、Sum of Digits

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值