【ICPC-202】uva 10624 - Super Number

点击打开链接

 

题目意思:  给定n和m 现在要求找到一个m位数的树使得,对于m的前i位数都是i的倍数,n <= i <= m, 而且这个数的第一位数不能为0,如果找到就输出这个数,否则输出-1

 

解题思路:    1  目前只懂得用深搜回溯做,只是这一题的数据没有想象中的那么大,所以加上一些剪枝即可水过(数据强的话肯定TLE)
                      2  我们知道这个解空间树有m层,每一层的可能取值有10种(第一个除外),那么最大的m = 29 ,那么时间复杂都就是 10^29次方,这么大的时间你敢用吗。由于这一 题的数据比较水,那么可以过。但是由于最大的数值超过了int,我们必须用数组模拟。
                      3  思路: 从第一层开始搜索,注意第一层不能为0,我们用k(这里第一层k = 1)表示当前的层数。对于k < n时候我们不用考虑能否被k整除直接往下搜素,当k >= n 时候我们就要考虑当前的这个大数能否被k整除,如果可以就往下继续搜索,最后如果当k > m时候说明已经找到了,并且我们已经从0开始搜索,那么得到的答案就是最小值,这时候可以直接输出
                      4  注意事项:由于刚开始,我认为前i-1个位数是不用要求被当前的位数整除,并且认为第一个数就是1,然后就开了一段WA历程,后来找到了数据才发现尼玛坑爹啊哥哥我错了。第一位值不一定为1,所以我们必须从第一层开始向下搜索至m层,所以看到这个m这么大,你敢这么做吗

 

代码:

 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
using namespace std;

int t , n , m , flag;
int ans[50];

//判断当前数值能否被整除
int judge_divisible(int *tmp , int k){
    int d = 0;//d是于数
    for(int i = 1 ; i <= k ; i++){//从小到大来模拟除法运算
        d = d*10+tmp[i];
        d %= k;
    }
    return d;//直接返回说明有没有于数存在
}

//深搜(就去枚举每一个位数的情况)
void dfs(int Tans[] , int k){
    if(k > m) { 
        memcpy(ans , Tans , sizeof(ans));
        flag = 1 ; return;
    }//如果当前的位数超过了m说明找到了这个标记flag为1
    for(int i = 0 ; i <= 9 ; i++){//枚举10个可能的值     
        Tans[k] = i;//令这个位数的数值为i,就去判断能否符合
        if(Tans[1] != 0){
           if(k < n || k >= n && !judge_divisible(Tans , k)) 
              dfs(Tans , k+1);//继续深搜
           if(flag) return;//找到了就直接返回不再去搜索就是剪枝
        }
    }
}

//主函数
int main(){
    //freopen("input.txt" , "r" , stdin);
    int i , j;
    scanf("%d" , &t);
    for(i = 1 ; i <= t ; i++){
        scanf("%d%d" , &n , &m); 
        memset(ans , 0 , sizeof(ans));
        flag = 0 ; dfs(ans , 1);
        printf("Case %d: " , i);
        if(flag){//如果当前有最小值输出这个值
            for(j = 1 ; j <= m ; j++) printf("%d" , ans[j]);
        }//没有的话输出-1
        else printf("-1");
        printf("\n");
    }   
    return 0;
}

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值