1. 程式人生 > >PAT乙級(C++)1021-1025

PAT乙級(C++)1021-1025

1021. 個位數統計

給定一個k位整數N = dk-1*10k-1 + … + d1*101 + d0 (0<=di<=9, i=0,…,k-1, dk-1>0),請編寫程式統計每種不同的個位數字出現的次數。例如:給定N = 100311,則有2個0,3個1,和1個3。

輸入格式:
每個輸入包含1個測試用例,即一個不超過1000位的正整數N。

輸出格式:
對N中每一種不同的個位數字,以D:M的格式在一行中輸出該位數字D及其在N中出現的次數M。要求按D的升序輸出。

輸入樣例:
100311
輸出樣例:
0:2
1:3
3:1

#include <iostream> 
#include <string> using namespace std; int main(){ string s; cin>>s; int num[10] ={0}; for(int i=0;i<s.length();i++){ num[s[i]-'0']++; } for(int i=0;i<10;i++){ if(num[i]!=0) cout<<i<<":"<<num[i]<<"\n"; } return
0; }

1022. D進位制的A+B

輸入兩個非負10進位制整數A和B(<=230-1),輸出A+B的D (1 < D <= 10)進位制數。

輸入格式:
輸入在一行中依次給出3個整數A、B和D。

輸出格式:
輸出A+B的D進位制數。

輸入樣例:
123 456 8
輸出樣例:
1103

#include <iostream>
using namespace std;
int main(){
    int a,b,d,sum,length;
    cin>>a>>b>>d;
    sum = a+b;
    int
result[32] = {0}; for(int i = 0;i<32;i++){ result[i] = sum%d; sum = (sum - result[i])/d; if(sum==0){ length = i; break; } } for(int i=length;i>=0;i--){ cout<<result[i]; } return 0; }

1023. 組個最小數

給定數字0-9各若干個。你可以以任意順序排列這些數字,但必須全部使用。目標是使得最後得到的數儘可能小(注意0不能做首位)。例如:給定兩個0,兩個1,三個5,一個8,我們得到的最小的數就是10015558。

現給定數字,請編寫程式輸出能夠組成的最小的數。

輸入格式:
每個輸入包含1個測試用例。每個測試用例在一行中給出10個非負整數,順序表示我們擁有數字0、數字1、……數字9的個數。整數間用一個空格分隔。10個數字的總個數不超過50,且至少擁有1個非0的數字。

輸出格式:
在一行中輸出能夠組成的最小的數。

輸入樣例:
2 2 0 0 0 3 0 0 1 0
輸出樣例:
10015558

#include <iostream>
using namespace std;
int main(){
    int count[10]={0};
    int start = 0;
    for(int i=0;i<10;i++){
        cin>>count[i];
    }
    if(count[0]==0){
        start = 1;
    }
    else{ //處理數字含0的特殊情況
        for(int i = 1;i<10;i++){
            if(count[i]!=0){
                cout<<i;
                count[i]--;
                while(count[0]!=0){
                    cout<<0;
                    count[0]--;
                }
                while(count[i]!=0){
                    cout<<i;
                    count[i]--;
                }
                start = i+1;
                break;
            }   
        }
    }
    for(int i=start;i<10;i++){
        while(count[i]!=0){
            cout<<i;
            count[i]--;
        } 
    }
    return 0;
 }

1024. 科學計數法

科學計數法是科學家用來表示很大或很小的數字的一種方便的方法,其滿足正則表示式[+-][1-9]”.”[0-9]+E[+-][0-9]+,即數字的整數部分只有1位,小數部分至少有1位,該數字及其指數部分的正負號即使對正數也必定明確給出。

現以科學計數法的格式給出實數A,請編寫程式按普通數字表示法輸出A,並保證所有有效位都被保留。

輸入格式:
每個輸入包含1個測試用例,即一個以科學計數法表示的實數A。該數字的儲存長度不超過9999位元組,且其指數的絕對值不超過9999。

輸出格式:
對每個測試用例,在一行中按普通數字表示法輸出A,並保證所有有效位都被保留,包括末尾的0。

輸入樣例1:
+1.23400E-03
輸出樣例1:
0.00123400
輸入樣例2:
-1.2E+10
輸出樣例2:
-12000000000

讀題的時候沒讀仔細——[數字的整數部分只有1位],傻傻地當做可能有很多位處理了。程式碼同樣適用,就懶得改了。

#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main(){
    string s;
    cin>>s;
    int index1 = s.find('.',0);
    int index2 = s.find('E',0);
    string s1,s2,s3;
    int move = 0;
    s1 = s.substr(0,index1);
    s2 = s.substr(index1+1,(index2-index1-1));
    s3 = s.substr(index2+1,s.size());

    for(int i=1;i<s3.size();i++){
        move = move*10 + (s3[i]-'0'); //move是小數點移動的次數 
    }
    if(s3[0]=='-'){
        move = 0-move;
    }
    if(s1[0] == '-'){//輸出符號
        cout<<s1[0];
        s1 = s1.substr(1,s1.size());
        index1--; 
        index2--;   
    }
    if(s1[0] == '+'){
        s1 = s1.substr(1,s1.size());
        index1--;
        index2--;   
    }

    if(index1+move<=0){//超出第1位,或者剛好第1位,前補0; 
        cout<<0<<'.';
        int i=index1+move;
        while(i<0){
            cout<<0;
            i++;
        }
        cout<<s1<<s2;   
    }
    else if(index1+move==index2-1){//剛好最末尾,不用輸出小數點 
        cout<<s1<<s2;
    }
    else if(index1 + move >index2-1){//超出最末尾,後補0 
        cout<<s1<<s2;
        int i = index1 + move - (index2-1);
        while(i>0){
            cout<<0;
            i--;
        }
    }
    else{
        cout<<s1;
        cout<<s2.substr(0,move);
        cout<<'.';
        cout<<s2.substr(move,s2.size());
    } 
    return 0;
}

1025. 反轉連結串列

給定一個常數K以及一個單鏈表L,請編寫程式將L中每K個結點反轉。例如:給定L為1→2→3→4→5→6,K為3,則輸出應該為3→2→1→6→5→4;如果K為4,則輸出應該為4→3→2→1→5→6,即最後不到K個元素不反轉。

輸入格式:
每個輸入包含1個測試用例。每個測試用例第1行給出第1個結點的地址、結點總個數正整數N(<= 105)、以及正整數K(<=N),即要求反轉的子鏈結點的個數。結點的地址是5位非負整數,NULL地址用-1表示。

接下來有N行,每行格式為:
Address Data Next

其中Address是結點地址,Data是該結點儲存的整數資料,Next是下一結點的地址。

輸出格式:
對每個測試用例,順序輸出反轉後的連結串列,其上每個結點佔一行,格式與輸入相同。

輸入樣例:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
輸出樣例:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

注意1:輸入中可能出現不在連結串列中的點,這些點不輸出
思路1:反轉的過程中採用首尾交換,節省時間。

#include <iostream>
using namespace std;
struct node{
    int address;
    int value;
    int next;
};

int main(){
    int start,N,K;
    cin>>start>>N>>K;
    node *ll = new node[N];
    node *sorted = new node[N];
    for(int i=0;i<N;i++){
        scanf("%d%d%d",&ll[i].address,&ll[i].value,&ll[i].next);
    }

    //按列表排序
    int count = 0; 
    for(int i=0;i<N;i++){
        int j;
        if(start == -1)
            break;  
        for(j=i;j<N;j++){ //此處j=i,是因為將取出的節點交換到前面,下次不必再訪問
            if(ll[j].address == start){
                sorted[i] = ll[j];
                start = ll[j].next; 
                node temp = ll[i];
                ll[i] = ll[j];
                ll[j] = temp;       
                count++;
                break;
            }               
        }   
    }

    //反轉 
    for(int i = 0;i<count/K;i++){
        int k = 1;
        for(int j=i*K;j<i*K+K/2;j++){
            node temp;
            temp = sorted[j];
            sorted[j] = sorted[i*K+K-k];
            sorted[i*K+K-k] = temp;
            k++;
        }

    }

    //輸出
    for(int i=0;i<count-1;i++){
        printf("%05d %d %05d\n",sorted[i].address,sorted[i].value,sorted[i+1].address);
    }
    printf("%05d %d %d\n",sorted[count-1].address,sorted[count-1].value,-1);            
    return 0;
}