您的位置:首页 > 其它

【基础训练-进制转换】decimal system

2018-01-24 09:24 127 查看
问题链接:UVA725
UVALive5362 Division。

题意简述

  输入正整数n,用0~9这10个数字不重复组成两个五位数abcde和fghij,使得abcde/fghij的商为n,按顺序输出所有结果。如果没有找到则输出“There are no solutions for N.”。这里2<=n<=79。

问题分析

  没有什么好办法,就暴力枚举吧!不过还是要下点功夫,否则10!的计算量是不可想象的。

  1.因为n>=2,且abcde=fghij×n,满足abcde>fghij。若a=0,则fghij的最小值为12345,abcde<fghij,矛盾。所以a≠0。

  2.因为a≠0,所以12345<=abcde<=98765,01234<=fghij。

  3.因为2≤n,且abcde≤98765,那么fghij = abcde/n,得fghij≤98765/2=49382,所以01234≤fghij≤49382。

  4.因为12345≤abcde≤98765,且01234≤fghij≤49382,所以用fghij进行枚举范围比较小。(这是在任意的n的条件下得出的结论)

  5.对于给定的n,因为abcde≤98765,那么fghij = abcde/n,得fghij≤98765/n。结论:01234≤fghij≤98765/n。

程序说明

  这可以说是最快枚举程序,比网上现有的暴力枚举程序要快。

AC的C语言程序如下:

[cpp] view
plain copy

/* UVA725 UVALive5362 Division */  

  

#include <stdio.h>  

#include <memory.h>  

  

#define DIGITNUM 10  

  

int check(int abcde, int fghij)  

{  

    int used[DIGITNUM], d;  

  

    memset(used, 0, sizeof(used));  

  

    if(fghij < 10000)  

        used[0] = 1;  

  

    while(abcde) {  

        d = abcde % 10;  

        if(used[d])  

            return 0;  

        used[d] = 1;  

  

        abcde /= 10;  

    }  

  

    while(fghij) {  

        d = fghij % 10;  

        if(used[d])  

            return 0;  

        used[d] = 1;  

  

        fghij /= 10;  

    }  

  

    return 1;  

}  

  

int main(void)  

{  

    int n, abcde, count, caseflag=0, end, i;  

  

    while(scanf("%d", &n) != EOF && n != 0) {  

        if(caseflag)  

            printf("\n");  

        caseflag = 1;  

  

        count = 0;  

        end = 98765 / n;  

        for(i=1234; i<=end; i++) {  

            abcde = i * n;  

            if(abcde >= 12345 && check(abcde, i)) {  

                printf("%05d / %05d = %d\n", abcde, i, n);  

                count++;  

            }  

        }  

        if(count == 0)  

            printf("There are no solutions for %d.\n", n);  

    }  

  

    return 0;  

}  

学到的点:
若用暴力枚举,可以再想想能不能通过理解题目要求后缩小范围,从而减短运行时长。

【基础训练-进制转换】decimal system
Input
There will be several cases. The first line of each case contains one integers N, and N means there will be N numbers
to import, then there will be N numbers at the next N lines, each line contains a number with such form : X1….Xn.(Y), and 0<=Xi<Y, 1<Y<=10. I promise you that the sum will not exceed the 100000000, and there will be at most 100 cases and the 0<N<=1000.
 

Output
There is only one line output case for each input case, which is the sum of all the number. The sum must be expressed
using the decimal system.
 

Sample Input

3 1(2) 2(3) 3(4) 4 11(10) 11(2) 11(3) 11(4)

 

Sample Output

6 23

 

Source
HDU
2007-6 Programming Contest

问题链接:HDU2106
decimal system。

问题分析

 这个问题是输入的数据进制各不相同要进行求和。

  关键是函数atoi()的原理要玩的很熟悉,才能够随心所欲地解决进制有关的问题。
  这里给出两种程序,一种是直接对字符串进行处理(使用函数strtok()切分值部分数字串和进制部分字符串),另外一种是暂时将不同进制的数当作10进制数进行处理,然后再转换。

#include <stdio.h>  

#include <stdlib.h>  

  

// 进制转换:将10进制的val转为base进制的值  

int change(int val, int base)  

{  

    int result = 0, weight = 1;  

    while(val) {  

        result += (val % 10) * weight;  

        val /= 10;  

        weight *= base;  

    }  

  

    return result;  

}  

  

int main(void)  

{  

    int n, base, val, sum, i;  

  

    while(scanf("%d", &n) != EOF) {  

        // 和清零  

        sum = 0;  

  

        // 读入各个数据,进行求和处理  

        for(i=1; i<=n; i++) {  

            scanf("%d(%d)", &val, &base);  

  

            // 累加  

            if(base == 10)  

                sum += val;  

            else  

                sum += change(val, base);  

        }  

  

        // 输出结果  

        printf("%d\n", sum);  

    }  

  

    return 0;  



 

学到的点:
注意这种不同形式的输入,得用C语言的scanf语句来进行数据提取。(红字部分)
进制转换是本来就会的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: