例80 ISBN 號碼
問題描述
每一本正式出版的圖書都有一個ISBN號碼與之對應,ISBN碼包括9位數字、1位識別碼和3位分隔符,其規定格式如x-xxx-xxxxx-x,其中符號-就是分隔符(鍵盤上的減號),最后一位是識別碼,例如0-670-82162-4就是一個標准的ISBN碼。ISBN碼的首位數字表示書籍的出版語言,例如0代表英語;第一個分隔符-之后的三位數字代表出版社,例如670代表維京出版社;第二個分隔符后的五位數字代表該書在該出版社的編號;最后一位為識別碼。
識別碼的計算方法如下:
首位數字乘以1加上次位數字乘以2……以此類推,用所得的結果mod11,所得的余數即為識別碼,如果余數為10,則識別碼為大寫字母X。例如ISBN號碼0-670-82162-4中的識別碼4是這樣得到的:對067082162這9個數字,從左至右,分別乘以1,2,...,9再求和, 0×1+6×2+……+2×9=158,然后取158 mod 11的結果4作為識別碼。
你的任務是編寫程序判斷輸入的ISBN號碼中識別碼是否正確,如果正確,則僅輸出Right;如果錯誤,則輸出你認為是正確的ISBN號碼。
輸入
一個字符序列,表示一本書的ISBN號碼(保證輸入符合ISBN號碼的格式要求)。
輸出
一行,假如輸入的ISBN號碼的識別碼正確,那么輸出Right,否則,按照規定的格式,輸出正確的ISBN號碼(包括分隔符-)。
輸入樣例
0-670-82162-0
輸出樣例
0-670-82162-4
(1)編程思路。
簡單的字符串模擬題。用循環對字符串中的前11個字符進行處理,計算出識別碼與最后一個字符比較,根據比較結果輸出相應信息。
(2)源程序。
#include <stdio.h> int main() { char isbn[14],ch; int i,k,s; scanf("%s",isbn); for (i=0,k=0,s=0;i<=10;i++) if (isbn[i]!='-') { k++; s+=k*(isbn[i]-'0'); } if (s%11==10) ch='X'; else ch=(s%11)+'0'; if (isbn[12]==ch) printf("Right\n"); else { isbn[12]=ch; printf("%s\n",isbn); } return 0; }
將此源程序提交給洛谷OJ題庫 P1055 ISBN 號碼(https://www.luogu.com.cn/problem/P1055)可以Accepted。
習題80
80-1 信用卡號的驗證
問題描述
當你輸入信用卡號碼的時候,有沒有擔心輸錯了而造成損失呢?其實可以不必這么擔心,因為並不是一個隨便的信用卡號碼都是合法的,它必須通過Luhn算法來驗證通過。
該校驗的過程:
1、從卡號最后一位數字開始,逆向將奇數位(1、3、5等等)相加。
2、從卡號最后一位數字開始,逆向將偶數位數字,先乘以2(如果乘積為兩位數,則將其減去9),再求和。
3、將奇數位總和加上偶數位總和,結果應該可以被10整除。
例如,卡號是:5432123456788881
則奇數位和=35
偶數位乘以2(有些要減去9)的結果:1 6 2 6 1 5 7 7,求和=35。
最后35+35=70 可以被10整除,認定校驗通過。
請編寫一個程序,從鍵盤輸入卡號,然后判斷是否校驗通過。通過顯示:“Right”,否則顯示“Wrong”。
輸入
一串信用卡號。
輸出
判斷結果。
輸入樣例
356827027232780
輸出樣例
成功
(1)編程思路。
簡單的字符串模擬題,用循環對字符串按題目要求進行處理。
(2)源程序。
#include <stdio.h> #include <string.h> int main() { char s[26]; scanf("%s",s); int sum=0,t; int i,f; for (i=strlen(s)-1,f=1;i>=0;i--,f=1-f) { if (f==1) sum+=s[i]-'0'; else { t=2*(s[i]-'0'); if (t>9) t-=9; sum+=t; } } if (sum%10==0) printf("Right\n"); else printf("Wrong\n"); return 0; }
80-2 寶石串
問題描述
有一種寶石串,由綠寶石和紅寶石串成,僅當綠寶石和紅寶石數目相同的時候,寶石串才最為穩定,不易斷裂。安安想知道從給定的寶石串中,可以截取一段最長的穩定的寶石串,有多少顆寶石組成。請你幫助他。
綠寶石用‘G’表示,紅寶石用‘R'表示。
輸入
一行由G和R組成的字符串
輸出
最長的穩定的寶石串有多少顆寶石組成
輸入樣例
GRGGRG
輸出樣例
4
(1)編程思路。
定義兩個數組int a[1000001],b[1000001];,其中a[i]和b[i]分別表示前一個寶石中綠寶石和紅寶石的個數,初始值全部為0。
用循環對寶石串進行掃描處理,計算出數組a和b各元素的值。
之后對區間[i,j](區間左端點從1~n,n為寶石串中寶石的個數;右端點從n~i)進行處理,若在某段區間中,綠寶石的個數a[j]-a[i-1]和紅寶石的個數b[j]-b[i-1]相等,則這段區間中的寶石可以構成穩定的寶石串,窮舉找到最長的區間即可。
(2)源程序。
#include <stdio.h> int a[1000001],b[1000001]; int main() { char str[1000001]; scanf("%s",str); a[0]=b[0]=0; int i,j; for (i=1;str[i-1]!='\0';i++) { if (str[i-1]=='G') { a[i]=a[i-1]+1; b[i]=b[i-1]; } else { b[i]=b[i-1]+1; a[i]=a[i-1]; } } int n=i-1; if (a[n]==0 || b[n]==0) { printf("0\n"); return 0; } int ans=0; for (i=1;i<=n;i++) // 區間左端點 { if (n-i+1<ans) break; for (j=n;j>=i;j--) { if (j-i+1<=ans) break; if (a[j]-a[i-1]==b[j]-b[i-1]) if (ans<j-i+1) ans=j-i+1; } } printf("%d\n",ans); return 0; }
將此源程序提交給洛谷OJ題庫 P2697 寶石串(https://www.luogu.com.cn/problem/P2697)可以Accepted。
80-3 方便記憶的電話號碼
問題描述
英文字母(除Q和Z外)和電話號碼存在着對應關系,如下所示:
A,B,C -> 2
D,E,F -> 3
G,H,I -> 4
J,K,L -> 5
M,N,O -> 6
P,R,S -> 7
T,U,V -> 8
W,X,Y -> 9
標准的電話號碼格式是xxx-xxxx,其中x表示0-9中的一個數字。有時為了方便記憶電話號碼,我們會將電話號碼的數字轉變為英文字母,如把263-7422記成America。有時,我們還加上“-”作為分隔符,如把449-6753記成Hi-World。當然,我們未必要將所有的數字都轉變為字母,比如474-6635可以記成iPhone-5。
總之,一個方便記憶的電話號碼由數字和除Q、Z外的英文字母組成,並且可以在任意位置插入任意多的“-”符號。
現在 ,我們有一個列表,記錄着許多方便記憶的電話號碼。不同的方便記憶的電話號碼可能對應相同的標准號碼,你的任務就是找出它們。
輸入
第一行是一個正整數n(n <= 100000),表示列表中的電話號碼數。
其后n行,每行是一個方便記憶的電話號碼,它由數字和除Q、Z外的英文字母、“-”符號組成,其中數字和字母的總數一定為7,字符串總長度不超過200。
輸出
輸出包括若干行,每行包括一個標准電話號碼(xxx-xxxx)以及它重復出現的次數k(k >= 2),中間用空格分隔。輸出的標准電話號碼需按照升序排序。
如果沒有重復出現的標准電話號碼,則輸出一行“No duplicates.”。
輸入樣例
12
4873279
ITS-EASY
888-4567
3-10-10-10
888-GLOP
TUT-GLOP
967-11-11
310-GINO
F101010
888-1200
-4-8-7-3-2-7-9-
487-3279
輸出樣例
310-1010 2
487-3279 4
888-4567 3
(1)編程思路。
編寫函數int ctoi(char ch),按英文字母(除Q和Z外)和電話號碼存在的對應關系,把字符ch轉換為對應的數字。
輸入時將所有的電話號碼全部轉換為全部由7位數字表示的電話號碼后進行保存,去掉輸入中的連接符“-”,將字母全部轉換為對應的數字。
將保存好的電話號碼按整數從小到大排列,這樣相同的號碼一定會排列在一起,用循環對排序好的數組進行掃描處理,重復次數超過2的電話號碼按要求格式輸出。
(2)源程序。
#include <stdio.h> #include <algorithm> using namespace std; int ctoi(char ch) // 把字符ch轉換為對應的數字 { if(ch=='A' || ch=='B' || ch=='C') return 2; if(ch=='D' || ch=='E' || ch=='F') return 3; if(ch=='G' || ch=='H' || ch=='I') return 4; if(ch=='J' || ch=='K' || ch=='L') return 5; if(ch=='M' || ch=='N' || ch=='O') return 6; if(ch=='P' || ch=='R' || ch=='S') return 7; if(ch=='T' || ch=='U' || ch=='V') return 8; if(ch=='W' || ch=='X' || ch=='Y') return 9; if (ch>='0' && ch<='9') return ch-'0'; } int main() { int n; //號碼數 scanf("%d",&n); int out[100001]; // 存放待輸出的電話號碼 int num,i,j; for(i=0;i<n;i++) { num=0; char s[201]; scanf("%s",s); for (j=0;s[j]!='\0';j++) { if(s[j]=='-' || s[j]=='Q' || s[j]=='Z') continue; num=num*10+ctoi(s[j]); } out[i]=num; } sort(out,out+n); int flag=1; // 標記是否所有號碼都是唯一的 i=0; while (i<n) { int times=0; // out[i]出現的次數 int k=out[i]; int sign=0; // 標記k出現次數是否大於2 while (i<n && k==out[i]) { times++; i++; if(times==2) { flag=0; sign=1; } } if (sign) { printf("%03d-%04d %d\n",k/10000,k%10000,times); } } if (flag) printf("No duplicates.\n"); return 0; }
將此源程序提交給北大OJ題庫 POJ 1002 487-3279(http://poj.org/problem?id=1002)可以Accepted。