题目链接:4114 5001 6004 8001 大整数加法
4114:思路就是找到空格的位置,然后将其逆序一下,存到另一个数组b里,最后把数组b输出来。记住输入字符串的时候要用gets,不要用scanf和cin,因为gets是以换行为结尾的,而scanf和cin是以空格为结尾的,这点需要注意一下。
//4114 单词逆序
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int n;
cin>>n;
getchar();
while(n--)
{
int m;
cin>>m;
getchar(); //吸收掉要输入的空行
while(m--)
{
char a[1010];
char b[1010];
gets(a); //不要用scanf和cin
int len=strlen(a);
int q=0; //q记录的是单词的个数减1,也就是说有q+1个单词要逆序
for(int i=0;i<len;i++)
{
if(a[i]==' ')
q++;
}
int f1=0,f2;
while(q--) //先对前q个单词逆序
{
for(int i=0;i<len;i++)
{
if(a[i]==' ')
{f2=i-1;a[i]='a';break;}
}
for(int i=f1,j=0;i<=f2;i++,j++)
{b[i]=a[f2-j];} //将逆序后的a存到数组b里
b[f2+1]=' ';
f1=f2+2;
}
//下面对最后一个单词进行逆序
f2=len-1;
for(int i=f1,j=0;i<=f2;i++,j++)
b[i]=a[f2-j];
b[f2+1]='\0'; //在字符串末尾加上'\0'
cout<<b<<endl;
}
cout<<endl;
}
return 0;
}
5001:只需要写出四个计算其相应进制的各位数字相加的和,然后枚举判断其是不是“特殊的四位数”(不同进制的各位数字和是否相等)即可。我感觉这道题的重难点就是计算相应进制的各位数字相加的和,如果这一点会的话,这个题基本就能做出来了。
//例5001 特殊的四位数
#include<iostream>
#include<cstdio>
using namespace std;
int ten(int x) //返回x十进制各位数字相加的和
{
return x%10+x/10%10+x/100%10+x/1000%10;
}
int sixteen(int x) //返回x十六进制各位数字相加的和
{
return x%16+x/16%16+x/256%16+x/(256*16)%16;
}
int twelve(int x) //返回x十二进制各位数字相加的和
{
return x%12+x/12%12+x/144%12+x/(144*12)%12;
}
bool ok(int x) //判断数字x是不是“特殊的四位数”
{
if(ten(x)==sixteen(x)&&ten(x)==twelve(x))
return true;
return false;
}
int main()
{
for(int i=1000;i<=9999;i++) //枚举,判断i是不是特殊的四位数,如果是就把它输出来
{
if(ok(i))
cout<<i<<endl;
}
return 0;
}
6004:因为他的出生日期是严格按照YYYY-MM-DD的格式输入的,所以就很简单了,将日期存到一个字符串里,然后用三个整型变量“取出”年、月、日。还有就是用数组存下1年到9999年的天数,主要就是判断它是平年还是闰年。然后要根据他出生的月份判断一下他十八岁的生日是第多少天。(实际上还要考虑他出生在几号,不过数据比较水,只考虑月份也能过)。还有一点,只有当他是在闰年2月29日出生并且他十八岁那年没有2月29号,他才没有18岁生日,这个时候输出-1。(实际上这个可以当作尝试记住,2月29出生的人是四年过一次生日)
//例6004 18岁生日
#include<iostream>
#include<cstdio>
using namespace std;
int num[100010]; //用来储存1到9999年的天数
int main()
{
for(int i=1;i<100010;i++)
{
if((i%4==0&&i%100!=0)||(i%400==0)) //判断其是否是闰年,如果为真就是闰年,否则就是平年
num[i]=366;
else
num[i]=365;
}
int n;
cin>>n;
getchar(); //吸收掉一个回车键
while(n--)
{
char e[20];
cin>>e;
int a,b,c;
a=(e[0]-48)*1000+(e[1]-48)*100+(e[2]-48)*10+(e[3]-48); //出生的年份
b=(e[5]-48)*10+(e[6]-48); //出生的月份
c=(e[8]-48)*10+(e[9]-48); //出生的日子
int ans=0; //用来存储最终的答案
if(b==2&&c==29) //此时他没有18岁生日
{cout<<-1<<endl;continue;}
if(b>2) //这里要注意一下
{
for(int i=a+1,j=1;j<=18;i++,j++)
ans+=num[i];
}
else
{
for(int i=a,j=1;j<=18;i++,j++)
ans+=num[i];
}
cout<<ans<<endl;
}
return 0;
}
8001:只需要用结构体存一下点的坐标,算一下各个点的距离,遍历一遍,找出最小的距离,将这个点的坐标存一下,输出即可。需要注意的是,因为精度的原因,找最小距离的时候需要做差,只要其差值小于1e9就可以认为这和距离最小。
//例8001 颜色映射
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
struct node{
int x,y,z;
}a[20]; //用结构体来存前16种颜色
int main()
{
for(int i=0;i<16;i++)
cin>>a[i].x>>a[i].y>>a[i].z;
int x,y,z;
while(cin>>x>>y>>z)
{
if(x==-1&&y==-1&&z==-1)
break;
double b[20]; //记住要定义double型的数组,因为算欧几里德距离会出现浮点型数据的情况
for(int i=0;i<16;i++)
b[i]=sqrt(double((a[i].x-x)*(a[i].x-x)+(a[i].y-y)*(a[i].y-y)+(a[i].z-z)*(a[i].z-z)));
//记住用sqrt函数要强制类型转换,否则交上去会Compile Error(编译错误)。好像是因为只有浮点型数据能用sqrt函数
int minn=100010; //把minn初始化成一个非常大的数
//切记要把minn定义到循环体里面,否则这次的循环会用到上次循环的值
//切记要把minn定义到循环体里面,否则这次的循环会用到上次循环的值
//切记要把minn定义到循环体里面,否则这次的循环会用到上次循环的值
//重要的事情说三遍
int k;
for(int i=0;i<16;i++)
{
if(b[i]-minn<1e-9) //需要注意这个地方的写法
{minn=b[i];k=i;}
}
cout<<"("<<x<<","<<y<<","<<z<<") maps to ("<<a[k].x<<","<<a[k].y<<","<<a[k].z<<")"<<endl;
}
return 0;
}
大整数加法:用字符数组存,模拟加法的过程即可,注意去除前导零。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
void re(char d[]) //一个逆序的函数
{
int len=strlen(d);
char e[210];
for(int i=0;i<len;i++)
{
e[i]=d[len-i-1];
}
for(int i=0;i<len;i++)
d[i]=e[i];
}
int main()
{
char a[210],b[210];
while(scanf("%s%s",a,b)!=EOF)
{
char c[210];
memset(c,0,sizeof c);
int lena=strlen(a);
int lenb=strlen(b);
re(a);
re(b);
int len=max(lena,lenb);
for(int i=lena;i<len;i++)
a[i]='0';
for(int i=lenb;i<len;i++)
b[i]='0';
for(int i=0;i<len;i++)
{
c[i]=char((a[i]-48+b[i]-48)%10+48);
c[i+1]+=char((a[i]-48+b[i]-48)/10+48);
}
for(int i=strlen(c)-1;i>=0;i--) //消除前导零
{
if(c[i]=='0')
c[i]='\0';
else
break;
}
re(c);
cout<<c<<endl;
}
return 0;
}