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)