目录
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