1. 程式人生 > >Day one

Day one

遞迴求解最大公約數

//遞迴求解最大公約數
#include<iostream>
using namespace std;

/*int gcd(int a,int b){   //老辦法
    int t,r;
    if(a < b){
        t = a;
        a = b;
        b = t;
    }
    if(b == 0){
       return a;
    }
    r = a%b;
    while(r != 0){
        a = b;
        b = r;
        r = a%b;
    }
    return b;
}
int gcd(int a,int b){
    if(a%b == 0){
        return b;
    }
    else{
        return gcd(b,a%b);
    }
}
*/
int gcd(int a,int b){ //炒雞簡單的遞迴 return a == 0?b:gcd(b%a,a); } int main(){ int x,y,t; cin>>x>>y; cout<<gcd(x,y)<<endl; return 0; }

字首和思想求解陣列從x到y之間的數值的和

講的是預處理的字首和思想

#include<iostream>
using namespace std;
const int N = 6;           //陣列元素個數

int
main(){ int a[N],x,y,sum[N],total; for(int i = 0;i < N;i++){ //輸入陣列元素 cin>>a[i]; } sum[0] = a[0]; for(i = 1;i < N;i++){ //對陣列元素預處理,sum[i]為陣列元素前i項之和 sum[i] = sum[i-1]+a[i]; } cin>>x>>y; if(x == 1){ total = sum[y-1]; } else
{ total = sum[y-1]-sum[x-2]; } cout<<total<<endl; return 0; }

還是字首和思想

#include<iostream>
using namespace std;

int main(){
    int n,m;
    cin>>n>>m;                    //n為陣列元素個數,m為求區間和的次數
    int *a = new int[n];          //動態分配陣列大小
    int *sum = new int[n];
    int *total = new int[m];
    int *x = new int[m];
    int *y = new int[m];
    for(int i = 0;i < n;i++){     //輸入陣列元素
        cin>>a[i];
    }
    for(int j = 0;j < m;j++){    //每行輸入兩個整數Xi,Yi 
        cin>>x[j]>>y[j];
    }
    sum[0] = a[0];
    for(i = 1;i < n;i++){      //對陣列元素預處理,sum[i]為陣列元素前i項之和
        sum[i] = sum[i-1]+a[i];
    }
    for(j = 0;j < m;j++){      //輸出m行,每行輸出一個整數,表示a[Xi]+a[Xi+1]+...+a[Yi]
        if(x[j] == 1){
            total[j] = sum[y[j]-1];
        }
        else{
            total[j] = sum[y[j]-1]-sum[x[j]-2];
        }
        cout<<total[j]<<endl;
    }
    delete[] a;
    delete[] sum;
    delete[] total;
    delete[] x;
    delete[] y;
    return 0;
}

以下是改進版,使用vector動態分配陣列,而不是用指標,可以避免指標用完之後忘記detele的錯誤

#include<iostream>
#include<vector>
using namespace std;

int main(){
    int n,m;
    cin>>n>>m;                    //n為陣列元素個數,m為求區間和的次數
    vector<int> a = new int[n];          //動態分配陣列大小
    vector<int> sum = new int[n];
    vector<int> total = new int[n];
    vector<int> x = new int[n];
    vector<int> y = new int[n];
    for(int i = 0;i < n;i++){     //輸入陣列元素
        cin>>a[i];
    }
    for(int j = 0;j < m;j++){    //每行輸入兩個整數Xi,Yi 
        cin>>x[j]>>y[j];
    }
    sum[0] = a[0];
    for(i = 1;i < n;i++){      //對陣列元素預處理,sum[i]為陣列元素前i項之和
        sum[i] = sum[i-1]+a[i];
    }
    for(j = 0;j < m;j++){      //輸出m行,每行輸出一個整數,表示a[Xi]+a[Xi+1]+...+a[Yi]
        if(x[j] == 1){
            total[j] = sum[y[j]-1];
        }
        else{
            total[j] = sum[y[j]-1]-sum[x[j]-2];
        }
        cout<<total[j]<<endl;
    }

    return 0;
}

Least common multiple (LCM)

http://acm.hdu.edu.cn/showproblem.php?pid=1019

The least common multiple (LCM) of a set of positive integers is the smallest positive integer which is divisible by all the numbers in the set. For example, the LCM of 5, 7 and 15 is 105.

Input
Input will consist of multiple problem instances. The first line of the input will contain a single integer indicating the number of problem instances. Each instance will consist of a single line of the form m n1 n2 n3 … nm where m is the number of integers in the set and n1 … nm are the integers. All integers will be positive and lie within the range of a 32-bit integer.

Output
For each problem instance, output a single line containing the corresponding LCM. All results will lie in the range of a 32-bit integer.

Sample Input
2
3 5 7 15
6 4 10296 936 1287 792 1

Sample Output
105
10296

最小公倍數(LCM)的一個正整數集是最小的正整數的集合中的所有數整除。
輸入
輸入將包括多個問題例項。輸入的第一行將包含一個整數,該整數表示問題例項的數量。
輸出
每個問題的例項,輸出一行,包含相應的模組。所有的結果將位於一個32位整數的範圍內。

炒雞簡單的題,應該最開始學C就練過的題,竟然把我弄得真的特別想哭,還是欲哭無淚的那種
以下分別是我弄過的n個最終提交的版本
首先1.0:看上去也特別簡單,就是先求兩個數的最大公約數,在兩個數相乘除以最大公約數即是最小公倍數。這時候我還沒注意到資料範圍,依然是先乘再除,但是這裡有在後面改過來了

#include<stdio.h>
int gcd(int a,int b){   //求兩個整數的最大公約數
    int t,r;
    if(a < b){
        t = a;
        a = b;
        b = t;
    }
    if(b == 0){
       return a;
    }
    r = a%b;
    while(r != 0){
        a = b;
        b = r;
        r = a%b;
    }
    return b;
}
int lcm(int a,int b){  //求兩個整數的最小公倍數
    return a/gcd(a,b)*b;
}
int main(){
    int n,x,i,r;
    scanf("%d",&n);         //多個問題例項的個數
    for(i = 0;i < n;i++){
        r = 1;
        do{
            scanf("%d",&x);
            r = lcm(r,x);    //r為前j個整數與第j+1個整數的最小公倍數
        }while(getchar() != '\n');
        printf("%d\n",r);
    }
    return 0;
}

這裡是1.1:應該是已經錯誤了很多次花了很多很多時間一個上午沒弄出來,下午又接著弄,弄著弄著放棄了接著晚上又來弄才出來的版本吧,因為顯示超時,就把兩個函式整合在一塊了

int lcm(int m, int n){
    int t,i = n,j = m;
    while ((m%n)!=0){
        t = n;
        n = m % n;
        m = t;
    }
    return i/n*j;
}

*不說廢話,直接上1.2。不過還是超時

#include <stdio.h> 
int gcd(int a,int b){
    return a == 0?b:gcd(b%a,a);
} 
int lcm(int a,int b){  //求兩個整數的最小公倍數
    return a/gcd(a,b)*b;
}
int main(){
    int n,x,i,r;
    scanf("%d",&n);         //多個問題例項的個數
    for(i = 0;i < n;i++){
        r = 1;
        do{
            scanf("%d",&x);
            r = lcm(r,x);    //r為前j個整數與第j+1個整數的最小公倍數
        }while(getchar() != '\n');
        printf("%d\n",r);
    }
    return 0;
}

AC通過的最終版本。好像是說多次函式呼叫需要很大的時間開銷,就把求最小公倍數的函式放在主函式內了。這道題通過的時候真的特別鬆了一口氣,特別開心。雖然說在這麼簡單的一道題上耗了這麼久真的很弱很弱,但是就好像你在攀登的過程中即使落後於大部隊,但是你還是終於看到了山腰的美景,這個過程越是艱難,你所獲得的成績感也就越多。這道題的小總結就是也算通過這道題熟悉了程式碼提交的系統,因為這個過程中一度懷疑是我的編譯器或者電腦的毛病,幸好沒有放棄

#include<stdio.h>
int gcd(int a,int b){
    if(b == 0){
        return a;
    }
    return gcd(b,a%b);
}    
int main(){
    int T;
    int n,a,b,i;
    int cnt;
    scanf("%u",&T);
    while(T--){
        scanf("%d",&n);
        cnt = a = 1;
        for(i = 1;i <= n;i++){
            scanf("%d",&b);
            cnt = a/gcd(a,b)*b;//換一下,先除後乘,免得資料溢位 
            a = cnt;
        } 
        printf("%d\n",cnt);   
    }    
    return 0;
} 

B - 進位制轉換

http://acm.hdu.edu.cn/showproblem.php?pid=2031

輸入一個十進位制數N,將它轉換成R進位制數輸出。
Input
輸入資料包含多個測試例項,每個測試例項包含兩個整數N(32位整數)和R(2<=R<=16, R<>10)。
Output
為每個測試例項輸出轉換後的數,每個輸出佔一行。如果R大於10,則對應的數字規則參考16進位制(比如,10用A表示,等等)。
Sample Input
7 2
23 12
-4 3
Sample Output
111
1B
-11

這道題也比較曲折。看程式碼吧

  #include <stdio.h> 
  #include <stdlib.h> 

int main(){ 
    char str[8],N[20],R[20];
    int n,r;
    int count = 0;
    while(scanf("%d%d",&n,&r)!=EOF){//輸入每個測試例項,包含兩個整數N(32位整數)和R(2<=R<=16, R<>10)
        N[count] = n;
        R[count] = r;
        count++;
    }
    for(int i = 0;i < count;i++){
        itoa(n,str,i);     //用函式轉換itoa(值,陣列名,進位制)
        printf("%s\n",str);
    }
    return 0;
}
#include<stdio.h>

int k = 0;               //用來記錄每一個進位制存放的位置
char str[20];            //用來存放每一個進位制的數
int N[20],R[20];   

void f(int n,int r){
    if(n == 0)
        return;
    f(n/r,r);
    str[k++] = n%r;  
} 

int main(){
    int n,r;
    int count = 0;
    while(scanf("%d%d",&n,&r)!=EOF){//輸入每個測試例項,包含兩個整數N(32位整數)和R(2<=R<=16, R<>10)
        N[count] = n;
        R[count] = r;
        count++;
    }
    for(int i = 0;i < count;i++){
        if(N[i] < 0){
            N[i] = -N[i];
            printf("-");
        }
        f(N[i],R[i]);
        for(int j = 0;j < k;j++){
            if(str[j] < 10)
                printf("%d",str[j]);
            else
                printf("%c",str[j]+'A'-10);
        }
        printf("\n");
        k = 0;
    }
    return 0;
}

小總結:第一天屬於對整個過程都非常陌生,自己真的特別特別弱,對比於那些大神,不要去過於追求練題的數量,要把做過的每一道題都給弄懂,另外還有很多很多需要學習和掌握的東西。Fighting!