MCS #5 丧心病AK专场 AC题解

TP地址

A - 签到

题目大意:
给出n个妹子学号,再给出其中n-1个妹子的学号,找出缺少的那个妹子的学号并输出。
思路:
这里要提一个叫做异或的神奇运算。c++中使用符号^来表示。异或运算的真值表见下:
x ^ y = z
0 0 = 0
1 0 = 1
0 1 = 1
1 1 = 0
简单地说异或运算就是同0异1,二进制中则是将2个二进制数字的每一位分别进行异或运算后输出结果,举个例子:
十进制c++异或运算1^10时,先将其转换成二进制0001和1010,然后分别对每位进行异或运算得到1011,就是11。
而异或真正神奇的地方在于,任何数异或自身等于0,0异或任何数等于该数,而且我神奇地发现,这个性质居然是满足交换律和结合律的!简单说就是a^x1^x2^x3^……^xn^a=x1^x2^x3^……^xn。
话说这有什么卵用呢?你没发现妹子的学号都是一个int型的整数么?只要将2次输入的共2*n-1个的整数全都异或起来,得到的结果就是结果啦!

#include <iostream>  
#include <stdio.h>  
#include <string.h>  
using namespace std;  

int main()  
{  
    int n;  
    char s[99],str[99];  
    cin>>n;  
    memset(str,0,sizeof(str));  
    for(int i=1;i<=n+n-1;i++)  
    {  
        scanf("%s",s);  //这里用的是字符串的形式来输入
        int len=strlen(s);  //但是没有关系
        for(int j=0;j<len;j++)  //反正字符都有ascii码
            str[j]=s[j]^str[j];    //一样能进行异或运算
    }                                  //是不是感觉很屌
    cout<<str<<endl;  
}  

C - Integer in C++

题目大意:给一个数,说出这个数改用short,int,longlong中那种结构来存储,若都不能,则输出It is too big!
思路:先看位数,小于5位肯定是short,6-9位肯定是int,11-18位肯定是long long,20位以上肯定是It is too big!若正好是5位,10位,19位,可用longlong来存储下这个数字然后与极限值比较(19位时可只比较后18位,因为不可能存在比9大的1个十进制数)。当然还有很多奇葩思路都能做,但之所以将这题的原因在于,奇葩的数据结构坑了我1个WA+3个CE。
首先是long long与__int64的纠缠关系,我不多说了= =
然后是double pow(double ,double)的使用。我不知道这该死的函数是个什么机制,当时我的想法是将每位数字上的字符减去’0’得到那位数值,然后乘pow(10.0,n)加到和sum去。当数值位数小的时候都很像样,然而算19位的时候发现,乘完的结果并不是后面一排0,而是多出了很多奇怪的数字。想了好久,估计是因为坑逼函数算出来的小数最后不是0的关系,在位数小的时候截断只到0而看不见后面的奇葩数字的关系。于是我写了下面的东西:

for(i=1;i<len;i++)
{
    if(len-i-1==18)tmp+=(x[i]-'0')*     1000000000000000000;
    else if(len-i-1==17)tmp+=(x[i]-'0')*100000000000000000;
    else if(len-i-1==16)tmp+=(x[i]-'0')*10000000000000000;
    else if(len-i-1==15)tmp+=(x[i]-'0')*1000000000000000;
    else if(len-i-1==14)tmp+=(x[i]-'0')*100000000000000;
    else if(len-i-1==13)tmp+=(x[i]-'0')*10000000000000;
    else if(len-i-1==12)tmp+=(x[i]-'0')*1000000000000;
    else if(len-i-1==11)tmp+=(x[i]-'0')*100000000000;
    else if(len-i-1==10)tmp+=(x[i]-'0')*10000000000;
    else if(len-i-1==9)tmp+=(x[i]-'0')* 1000000000;
    else if(len-i-1==8)tmp+=(x[i]-'0')* 100000000;
    else if(len-i-1==7)tmp+=(x[i]-'0')* 10000000;
    else if(len-i-1==6)tmp+=(x[i]-'0')* 1000000;
    else if(len-i-1==5)tmp+=(x[i]-'0')* 100000;
    else if(len-i-1==4)tmp+=(x[i]-'0')* 10000;
    else if(len-i-1==3)tmp+=(x[i]-'0')* 1000;
    else if(len-i-1==2)tmp+=(x[i]-'0')* 100;
    else if(len-i-1==1)tmp+=(x[i]-'0')* 10;
    else tmp+=(x[i]-'0');
}

(别叫我丧心病狂,我丧心病狂的时候才不只这么点水平呢)
然而还是WA了(还好我及时发现没有提交= =)。自己测试的时候发现,若是1个19位的数字且第9位数字非0在执行上面程序的时候,转换出来的数值会变得很奇葩。于是我打开了VS,设置了断点,玩了半天鼠标发现第9位的数字怎么算都不对,于是加了一个变量a,用来测试一下(x[i]-‘0’)* 1000000000的值,即改成下面这个样子

else if(len-i-1==9)tmp+=a=(x[i]-'0')* 1000000000;

发现a会算出一个很奇葩的数字而不是一排0。后来我又在10和8的那行分别加入了a

else if(len-i-1==10)tmp+=a=(x[i]-'0')*10000000000;
else if(len-i-1==9)tmp+=a=(x[i]-'0')* 1000000000;
else if(len-i-1==8)tmp+=a=(x[i]-'0')* 100000000;

结果又发现10和8的a都是一排0,只有9处的a是坑爹的。后来依次找了翻译、萝莉、二狗,结果都是统一回复:
“你写的什么鬼,就不能用函数吗?”
坑爹啊!会用函数我还写这个干嘛!当然逼还是要装的,后来二狗研究半天给上面的程序玩了好久的排版结果什么卵都没用= =。在我深思熟虑后终于发现了猫腻,将程序改成了这个样子

else if(len-i-1==9)tmp+=((long long )(x[i]-'0'))*1000000000;

然后我就A了囧rz=З。
因为这一行正好是int的极限位数,而1000000000是int,(x[i]-‘0’)也是int,那么结果当然也是int型,然后它就爆了。爆了之后在转换成long long储存起来所以造成异常。而小于9时int不会爆,大于9时后面那一排0是个long long 型的数,int*long long会自动将int 转换成long long再计算所以也不会错。
二狗:“你说得很有道理”
要你们何用╭( ̄m ̄*)╮
于是我最后的代码是这样的

#include<cstdio>
#include<iostream>
#include<queue>

using namespace std;

#include<stdio.h>
#include<string.h>
#include<math.h>
int main()
{
    char x[35];
    int len;
    const long long  max_ll=223372036854775807;
    const long long  max_i=2147483647;
    const long long  max_s=32767;
    unsigned long long tmp,a;
    int i;
    while(~scanf("%s",x))
    {
        len=strlen(x);
        if(len>19)
        {
            printf("It is too big!\n");
            continue;
        }
        tmp=0;
        if(len>10)
        {
            for(i=1;i<len;i++)
            {
                if(len-i-1==18)         tmp+=(x[i]-'0')*    1000000000000000000;
                else if(len-i-1==17)    tmp+=(x[i]-'0')*    100000000000000000;
                else if(len-i-1==16)    tmp+=(x[i]-'0')*    10000000000000000;
                else if(len-i-1==15)    tmp+=(x[i]-'0')*    1000000000000000;
                else if(len-i-1==14)    tmp+=(x[i]-'0')*    100000000000000;
                else if(len-i-1==13)    tmp+=(x[i]-'0')*    10000000000000;
                else if(len-i-1==12)    tmp+=(x[i]-'0')*    1000000000000;
                else if(len-i-1==11)    tmp+=(x[i]-'0')*    100000000000;
                else if(len-i-1==10)    tmp+=(x[i]-'0')*    10000000000;
                else if(len-i-1==9)     tmp+=((long long )(x[i]-'0'))*  1000000000;
                else if(len-i-1==8)     tmp+=(x[i]-'0')*    100000000;
                else if(len-i-1==7)     tmp+=(x[i]-'0')*    10000000;
                else if(len-i-1==6)     tmp+=(x[i]-'0')*    1000000;
                else if(len-i-1==5)     tmp+=(x[i]-'0')*    100000;
                else if(len-i-1==4)     tmp+=(x[i]-'0')*    10000;
                else if(len-i-1==3)     tmp+=(x[i]-'0')*    1000;
                else if(len-i-1==2)     tmp+=(x[i]-'0')*    100;
                else if(len-i-1==1)     tmp+=(x[i]-'0')*    10;
                else                    tmp+=(x[i]-'0')*    1;
            }
            if(tmp<=max_ll)printf("long long\n");
            else printf("It is too big!\n");
        }
        else if(len<=10&&len>5)
        {
            for(i=0;i<len;i++)
            {
                tmp+=(x[i]-'0')*pow(10.0,len-i-1);
            }
            if(tmp<=max_i)printf("int\n");
            else printf("long long\n");
        }
        else if(len<=5)
        {
            for(i=0;i<len;i++)
            {
                tmp+=(x[i]-'0')*pow(10.0,len-i-1);
            }
            if(tmp<=max_s)printf("short\n");
            else printf("int\n");
        }
    }
    return 0;
}

(看看就好,不要和我学o(-“-)o)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值