简单枚举系列之UVa_725除法【例题】

UVa 725 除法(Division)

【题目引用】

输入正整数n,按从小到大的顺序排列所有形如abcde/fghij=n的表达式,其中a-j恰好为数字输入0-9的一个排列(可以有前导0),2<=n<=79.
样例输入:62
样例输出:
79546/01283=62
94736/01528=62

【题目分析】

题目中说明了a~j是一个0~9的一个全排列,所以这里就隐含着10个数字出现且仅出现一次。那么有没有必要全部枚举呢?这里是不需要的,因为直接可以根据fghij推出abcde的值是多少(abcde=fghij*n),这里就很方便的计算出来的。什么时候可以终止这个枚举的情况呢?也就是说总共的位数超过了10位(一共就10个数字)也就是指分母或分子超过了这个值。

【实际问题】

  1. 如何确定循环的最小值?从哪开始?

    1. n最大是两位数,最小是一位数,所以要构成10位数,则需fghij是四位数以上
    2. 从四位数的最小值开始,且四位数中的数字只出现一遍,可见最小值为1234(0被作用于开头作为前导,不然个数不够)
  2. 如何确定枚举的最大值

    1. 这里可以直接定义该值为99999,但是这种情况并不会出现,所以不合理,优化算法不建议此做法
    2. 根据问题1答案的方式推算,那么可以达到的最大唯一的五位数值应该是98765
  3. 如何确定序列中数字的唯一性?

    1. 可以使用map映射,判断对应的键其值是否为1
    2. 也可以使用数组进行标记,因为数字较小,所以使用数组也蛮简单的。用数组模拟键-值

【代码实现】

#include <iostream>
#include <cstring>
#define MAX 98765
using namespace std;
int visited[10]; //全局数组会默认全为0
bool saveToArray(int value){
    //如果value_ed是四位的  那么前导0是必须存在的
    if(value < 10000) visited[0] = 1;
    while(value){
        if(visited[value%10] != 0) return false;
        visited[value%10] = 1;
        value/=10;
    }
    return true;
}

int main() {
    int n;

    while(cin >> n && n){
        int mark = 0;
        for(int value_ed = 1234; value_ed <= MAX;++value_ed)
        {

            memset(visited,0, sizeof(visited));
            int value_ing = value_ed*n;
            //判断该值是否是大于最大值的?
            if(value_ing > MAX) continue;
            //判断数字是不是唯一出现的
            int k = 0;
            if(!saveToArray(value_ed)) continue;
            //另一个数一定是5位的,不存在超过或者小于
            for(;k<5;++k){
                if(visited[value_ing%10] != 0) break;
                //记得边判断边标记
                else if(visited[value_ing%10] == 0) visited[value_ing%10]=1;
                value_ing /=10 ;
            }
            //k以5跳出则说明没有重复
            if(k == 5)
            {
                mark = 1;
                if(value_ed < 10000)
                    printf("%d / 0%d = %d\n",value_ed*n,value_ed,n);
                else
                    printf("%d / %d = %d\n",value_ed*n,value_ed,n);
            }

        }
        if(!mark) puts("No number!");

    }
    
    return 0;
}

ps:参考文章中,个人觉得int范围已经足够以表达数值了,无须定义为Long类型.
如果上述代码或者描述有错误,可以在评论区评论噢,喜欢的点个赞哈!

【参考文章】

Uva725 除法
《算法竞赛入门经典》第2版.刘汝佳

发布了30 篇原创文章 · 获赞 6 · 访问量 7979

猜你喜欢

转载自blog.csdn.net/weixin_42792088/article/details/104786527
今日推荐