Day one

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a1128o/article/details/51907853

递归求解最大公约数

//递归求解最大公约数
#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!

猜你喜欢

转载自blog.csdn.net/a1128o/article/details/51907853