学算法笔记的题解记录:
3_1简单模拟题
文章目录
- List item
- A. 剩下的树
- B. A+B
- C. 特殊乘法
- D. 比较奇偶个数
- E. Shorest Distance
- F. A+B和C
- G. 数字分类
- H. 部分A+B
- I. 锤子剪刀布
问题 A: 剩下的树
题目描述
有一个长度为整数L(1<=L<=10000)的马路,可以想象成数轴上长度为L的一个线段,起点是坐标原点,在每个整数坐标点有一棵树,即在0,1,2,…,L共L+1个位置上有L+1棵树。
现在要移走一些树,移走的树的区间用一对数字表示,如 100 200表示移走从100到200之间(包括端点)所有的树。
可能有M(1<=M<=100)个区间,区间之间可能有重叠。现在要求移走所有区间的树之后剩下的树的个数。
这个题目,最开始我是想通过设置一个数组,所有的数都设置为零,在移走区间里面的数设置为1。最后再遍历一下数组,统计为零的数有多少,然后一想,设置一个统计移走树数量的变量,在设置数为1时,将其加1,最后用总的树去减就是剩余树的数量,所以代码如下
#include<stdio.h>
#include<string.h>
int main()
{
int l,m;
while(scanf("%d%d",&l,&m) != EOF){
if(l==0 && m==0) break; //需要注意输入数据,根据两个数都为零为结束标志。
int a[l+1],sum=0; //便于输入的数据之间使用
memset(a,0,sizeof(a));
while(m--){
int x,y; //表示移走树的区间长度
scanf("%d%d",&x,&y);
for(;x<=y;x++){
if(a[x]!=1){ //若该处还有树
a[x] = 1;
sum++;
}
}
}
printf("%d\n",l-sum+1);
}
return 0;
}
问题 B: A+B
题目描述 给定两个整数A和B,其表示形式是:从个位开始,每三位数用逗号","隔开。 现在请计算A+B的结果,并以正常形式输出。
输入 输入包含多组数据数据,每组数据占一行,由两个整数A和B组成(-10^9 < A,B < 10^9)。
输出 请计算A+B的结果,并以正常形式输出,每组数据占一行。
样例输入
-234,567,890 123,456,789
1,234 2,345,678
样例输出
-111111101 2346912
输入数据有’,’ 所以将以字符串str1的形式接受,然后将该字符串数字和符号信息复制到另一字符数组str2中(类似于删除所有的逗号),再通过sscanf(str2,"%d",&a);将其转化为所需的数据,之后相加得到数据输出。
//3_1 B A+B
#include<stdio.h>
#include<string.h>
int main()
{
int change(char s[]); //转化函数,将输入的数据转化为整数。
char a[20],b[20];
while(scanf("%s %s",a,b)!=EOF){
int num1,num2;
num1 = change(a);
num2 = change(b);
printf("%d\n",num1+num2);
}
return 0;
}
int change(char s[]){
int num,n,i,j;
char s1[20];
n = strlen(s);
for(i=0,j=0;i<n;i++){
if((s[i]>='0' && s[i]<='9')|| s[i]=='-'){
s1[j++] = s[i];
}
}
s1[j] = '\0';
sscanf(s1,"%d",&num);
return num;
}
问题 C: 特殊乘法
题目描述 写个算法,对2个小于1000000000的输入,求结果。特殊乘法举例:123 * 45 = 14 +15 +24 +25+34+35 输入 两个小于1000000000的数
输出 输入可能有多组数据,对于每一组数据,输出Input中的两个数按照题目要求的方法进行运算后得到的结果。
样例输入
24 65
42 66666
3 67
样例输出 66 180 39
将每个数都转化一个数组,数组的元素为数中的每一位,之后两个数组中的元素逐一相乘,累加后得到正确答案。
#include<stdio.h>
int main()
{
int convert(int s[],int num); //将数中的每一位赋值给数组中的相应位置,并返回数的位数。
int a[20],b[20];
int num1,num2; // 分别记录两个数组的使用长度,即数的位数,方便使用。
while(scanf("%d%d",&num1,&num2) != EOF){
int n1 = convert(a,num1);
int n2 = convert(b,num2);
int i,j,sum=0;
for(i=0;i<n1;i++){
for(j=0;j<n2;j++){
sum += a[i]*b[j];
}
}
printf("%d\n",sum);
}
}
int convert(int s[],int num){
int n=0;
while(num!=0){
s[n++] = num%10;
num /= 10;
}
return n;
}
问题 D: 比较奇偶数个数
题目描述 第一行输入一个数,为n,第二行输入n个数,这n个数中,如果偶数比奇数多,输出NO,否则输出YES。 按照题意编写即可,代码如下
:
// 3_1 D 比较奇偶个数
#include<stdio.h>
int main()
{
int n;
while(scanf("%d",&n) != EOF){
int a,p=0,o=0; //p表示偶数,o表示奇数
while(n--){
scanf("%d",&a);
if(a%2==0){
p++;
}else o++;
}
if(p>o){
printf("NO\n");
} else printf("YES\n");
}
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
因为是循环数组,所以把所有路径的总长度求出来,再设置一个数组存放任一个点到起始点的位置(提前设置,防止每次使用都要重新遍历,导致时间超出),每输入一个数的时候就进行求出,两点之间的两个距离,进行比较,然后输出。代码如下
//A1046 Shortest Distance
#include<stdio.h>
/*既然是循环队列,所以可能是顺序到达,也可能是逆序到达。
所以每次都遍历整个数组,在范围内的加起来,不在的也加起来 ,取最小值*/
int main()
{
int n,n1;
scanf("%d",&n);
int x[n+1],dis[n+1],i,sum=0; // x[i]存放循环数组,dis数组防止到每个点的距离,sum为循环链总长度
for(i=1;i<=n;i++){
scanf("%d",&x[i]);
sum += x[i];
dis[i] = sum;
}
scanf("%d",&n1);
while(n1--){
int left,right;
int sum1=0,sum2=0;
scanf("%d%d",&left,&right);
if(left>right){ //默认left 小于 right
int t = left;
left = right;
right = t;
}
sum1 = dis[right-1] - dis[left-1];
sum2 = sum-sum1;
if(sum1>sum2){
printf("%d\n",sum2);
}else printf("%d\n",sum1);
}
return 0;
}
问题 F: A+B和C (15)
题目描述
给定区间[-231, 231]内的3个整数A、B和C,请判断A+B是否大于C。
按照题意写出代码即可,注意整数的取值范围,要用long
//3_1 F A+B和C
#include<stdio.h>
//注意数据范围,需要长整型
int main()
{
char *t = "true";
char *f = "false",*q;
int n,num=0;
scanf("%d",&n);
while(n--){
long a,b,c;
scanf("%ld%ld%ld",&a,&b,&c);
if(a+b>c){
q = t;
}else q = f;
num++;
printf("Case #%d: %s\n",num,q);
}
return 0;
}
问题 G: 数字分类 (20)
题目描述
给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字:
A1 = 能被5整除的数字中所有偶数的和;
A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4…;
A3 = 被5除后余2的数字的个数;
A4 = 被5除后余3的数字的平均数,精确到小数点后1位;
A5 = 被5除后余4的数字中最大数字。
代码如下,想法是多分支结构,简单模拟,需要注意的是A1的数是偶数,需要再判断一下
//3_1 G 数字分类
#include<stdio.h>
#include<string.h>
int main()
{
int n,i;
while(scanf("%d",&n) != EOF){
int a[2][5],m = 1,x; // 二维数组,分别存放某种类别数量,和该种情况下的结果数
double avg = 0; //接收A4的数据
memset(a,0,sizeof(a));
while(n--){
int index = 0;
scanf("%d",&x);
index = x%5; // 根据余数来判断是那种类型
a[0][index]++;
switch(index){
case 0:
if(x%2==0){ //注意这里是要偶数
a[1][index] += x;
}else a[0][index]--;
break;
case 1:
a[1][index] += (x*m);
m *= -1;
break;
case 2:
a[1][index]++;
break;
case 3:
avg += x;
break;
case 4:
if(x>a[1][index]){
a[1][index] = x;
}
break;
}
}
for(i=0;i<5;i++){
if(a[0][i]!=0){
if(i != 3){ // 特殊情况特殊处理
printf("%d ",a[1][i]);
}else printf("%.1f ",avg/a[0][i]);
}else printf("N ");
}
printf("\n");
}
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。
输入
输入在一行中依次给出A、DA、B、DB,中间以空格分隔,其中0 < A, B < 1010。
输出
在一行中输出PA + PB的值。
样例输入
3862767 6 13530293 3
3862767 1 13530293 8
样例输出
399
0
按照题意将两个部分数求出来,再相加即可
//3_1 H 部分A+B
#include<stdio.h>
#include<string.h>
int main(){
int new_p(int x,int dx); // 将x中和dx一样的数,组成一个新的数
int mul_n(int n,int x); // 将x变为n个x组合,例如,x=3,n=2 返回的数为33
int a,da,b,db;
while(scanf("%d%d%d%d",&a,&da,&b,&db) != EOF){
int pa,pb;
pa = new_p(a,da);
pb = new_p(b,db);
printf("%d\n",pa+pb);
}
return 0;
}
int new_p(int x,int dx){// 将x中和dx一样的数,组成一个新的数
int a[10],num =0,i;
memset(a,0,sizeof(a));
while(x != 0){
int index = x%10;
x /= 10;
a[index]++;
}
for(i=0;i<10;i++){
if(i==dx && a[i]!=0){
num = mul_n(a[i],dx);
break;
}
}
return num;
}
int mul_n(int n,int x){ // 将x变为n个x组合,例如,x=3,n=2 返回的数为33
int m = 1,sum = 0;
while(n--){
sum += (m*x);
m *= 10;
}
return sum;
}
问题 I: 锤子剪刀布 (20)
题目描述
大家应该都会玩“锤子剪刀布”的游戏:两人同时给出手势,胜负规则如图所示:
现给出两人的交锋记录,请统计双方的胜、平、负次数,并且给出双方分别出什么手势的胜算最大。
这个我用了超级蠢的办法,不建议使用,代码如下
//3_1 I 锤子剪刀布
#include<stdio.h>
#include<string.h>
int main()
{
int n ,win =0,loses=0,com=0,x[3],y[3],max1=0,max2=0;
int i=0;
char b1,b2;
scanf("%d",&n);
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
getchar();
while(n--){
char a,b;
scanf("%c %c",&a,&b);
// printf("%c 1111 %c\n",a,b);
getchar();
switch(a){
case 'B':
switch(b){
case 'B':com++;break;
case 'C':win++;x[0]++;break;
case 'J':loses++;y[2]++;break;
}break;
case 'C':
switch(b){
case 'C': com++;break;
case 'J': win++;x[1]++;break;
case 'B': loses++;y[0]++;break;
}break;
case 'J':
switch(b){
case 'C':loses++;y[1]++;break;
case 'J':com++;break;
case 'B': win++;x[2]++;break;
}break;
}
}
for(i=0;i<3;i++){
if(x[i]>x[max1]){
max1 = i;
}
if(y[i]>y[max2]){
max2 = i;
}
}
printf("%d %d %d\n",win,com,loses);
printf("%d %d %d\n",loses,com,win);
switch(max1){
case 0: b1='B';break;
case 1: b1= 'C';break;
case 2:b1= 'J';break;
}
switch(max2){
case 0: b2= 'B';break;
case 1: b2= 'C';break;
case 2: b2 = 'J'; break;
}
printf("%c %c\n",b1,b2);
return 0;
}
这个题另一种思路是找到其中的规律,用数组来表示其中的逻辑。
模拟的话,目前就这样吧。