思路,提取数字,比较尾数,为啥只有10分

P1055 [NOIP2008 普及组] ISBN 号码

首先输入最后一位数字有可能是X(罗马数字10),需要特判。 如果所给序列不对输出来的也不是原序列,这句: ```cpp cout<<word[0]<<"-"<<word[1]<<word[2]<<word[3]<<"-"<<word[4]<<word[5]<<word[6]<<word[7]<<word[8]<<"-"<<word[9]; ``` 最后应该是end_word,但是输出还需要考虑'X'。 再说一点,你不把样例复制下来放到程序里面验证一下?样例都不过,粘贴的时候点窗口左上角找到编辑->粘贴。
by Terrible @ 2020-02-17 16:59:24


@[Terrible](/user/195942) 10分表示就过了样例;还有就是请问罗马数字X大小是10吗,什么情形下需要考虑X的存在?
by zhuyi3625 @ 2020-02-17 17:19:51


```cpp 首位数字乘以1加上次位数字乘以2……以此类推,用所得的结果mod11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。 ``` 认真看题,找找ASCII表,在ASCII表中数字'0'~'9'在一块,'a'~'z'在一块,'A'~'Z'在一块,可以看看其对应的数字,但是我们一般在程序中写'X'就代表'X'对应的数字。 ```cpp if(a[i]=='X') word[j]=10; else { word[j]=a[i]-'0'; ++j; } ``` 最后输出的时候需要特判end_word,如果为10,则输出'X'。
by Terrible @ 2020-02-17 17:42:44


样例有两个,样例2你没过。测试点很**坑**另9个测试点几乎都跟X有关,理解题意很重要。
by Terrible @ 2020-02-17 17:48:51


特别附注:身份证最后面一位也可以有11种,0,1,2,3,4,5,6,7,8,9,X,都在ASCII的范畴内,真正的罗马数字是‘Ⅹ’,不在ASCII范畴内,属于**万国码**(Unicode),表示出来需要2字节,汉字也是2字节。一般来说能用ASCII不用Unicode,ASCII规范形成早于Unicode。
by Terrible @ 2020-02-17 17:56:08


@[Terrible](/user/195942) 明白了,感谢耐心的解答
by zhuyi3625 @ 2020-02-19 14:08:39


@[Terrible](/user/195942) 已AC,之前考虑的不够全面,忘了整型和字符型的不同,也没考虑到10;思路还是一个思路,不过只是实现了计算,优化方面有点吃力
by zhuyi3625 @ 2020-02-19 15:05:00


@[Terrible](/user/195942) ``` #include<iostream> #include<cstdio> using namespace std; int main() { char a[14]; int word[10]; char end_number; int j=0;//存储数字用的序号 int i,sum=0,end_word; gets(a); for(i=0;i<13;++i)//提取数字 { if(a[i]=='-') { continue; } else//a[i]不是分隔符情况下 { word[j]=a[i]-'0'; if(a[i]=='X') { word[9]=10; continue; } ++j; } } //此时有10个j,最大为j[9] for(i=0;i<9;++i) { sum+=word[i]*(i+1);//求和 } end_word=sum%11;//此时所有数据计算完毕 //需要将整形转化为字符型进行输出 if(word[9]==end_word) { cout<<"Right"; } else if(end_word==10) { end_number='X'; cout<<word[0]<<"-"<<word[1]<<word[2]<<word[3]<<"-"<<word[4]<<word[5]<<word[6]<<word[7]<<word[8]<<"-"<<end_number; } else { cout<<word[0]<<"-"<<word[1]<<word[2]<<word[3]<<"-"<<word[4]<<word[5]<<word[6]<<word[7]<<word[8]<<"-"<<end_word; } return 0; }
by zhuyi3625 @ 2020-02-19 15:08:41


@[zhuyi3625](/user/314719) 我写了地比较密集,不过思路上更简洁了。 ```cpp #include<cstdio> int main() { char c[15],end; int i,j,sum=0; scanf("%s",c); for(i=0,j=1;i<11;i++) if(c[i]!='-') sum+=(j++)*(c[i]-'0'); sum%=11; end=(sum==10)?'X':sum+'0'; if(end==c[12]) printf("Right"); else { for(i=0;i<12;i++) putchar(c[i]); putchar(end); } } ``` ###### 书写上: 我一般不用多余的{ }行数就能减少。 ```cpp if(判断表达式) 语句; if(判断表达式) { n个语句; } //这两种形式是等价的,不过花括号之间可以有好多个并列语句。 ``` ###### 思路上: ①录入字符串。②扫描一遍字符串,不过最后两个字符这个时候不用管,如果不是'-'那么这个字符就是数字,j从1到9遇到数字就+1,把数字(转化成int型)和j相乘,得出sum。③然后让end表示算出的最后一个字符。这样我们就不必考虑'-'的位置了。 ```cpp end=(sum==10)?'X':sum+'0'; //d1?d2:d3 是三目表达式 //如果d1取非零的数(为真),那么表达式返回d2 //如果d1取零(为假),那么表达式返回d3 //它等价于: if(sum==10) end='X'; else end=sum+'0'; ``` ④此时最后的字符已经算出来了,我们与原来的对比。最后输出。此时也不必考虑'-'的位置。
by Terrible @ 2020-02-19 17:59:09


@[Terrible](/user/195942) 学习了,这个三目运算符有点闪眼睛
by zhuyi3625 @ 2020-02-20 14:47:30


|