您的位置:首页 > 其它

NENU 17级算法学习小组 Round 5 0627

2018-06-27 21:54 127 查看

题目链接: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;
}


阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: