ACM: 有难度的深搜题 poj 3373

来源:互联网 发布:深圳阿里云大厦 编辑:程序博客网 时间:2024/06/16 09:28

                                                          Changing Digits

Description

Given two positive integers n and k, you areasked to generate a new integer, say m, by changing some(maybe none) digits of n, such that the followingproperties holds:

  1. m contains no leading zeros and has the same length asn (We consider zero itself a one-digit integerwithout leading zeros.)
  2. m is divisible by k
  3. among all numbers satisfying properties 1 and 2, mwould be the one with least number of digits different fromn
  4. among all numbers satisfying properties 1, 2 and 3, mwould be the smallest one

Input

There are multiple test cases for the input. Each test caseconsists of two lines, which containsn(1≤n≤10100) andk(1≤k≤104, kn) foreach line. Both n and k will not contain leadingzeros.

Output

Output one line for each test case containing the desired numberm.

Sample Input

2

2

619103

3219

Sample Output

2

119103

题意: 现在给你两个数n , k. 要求一个新的数m.

         满足四个要求:

                                (1). m没有前导0和长度和n一样长.

                                (2). 可以被k整除.

                                (3). 满足1,2的前提下, 尽量满足m和n的每位尽量相同.

                                (4). 满足1,2,3的前提下, 使m最小.

解题思路:

                1. 题目规模是n <= 10^100 , k <= 10^4.高精度,并且直接求余绝对不行. 对余数打表.

                2. 采用深搜, 把n修改这样就可以保证条件3满足.

                3. 同时要求最小的. 搜索的顺序应该先搜索小于当前位的值. 然后再搜索大于的.满足最小了.

                4. 这样直接暴搜结果TLE了.  从网上讨论找到剪枝的方法.

                设 remember[i][j] = c 表示 剩余替换次数为i,当前余数为j时 , index在区间[0,c-1]时都不成立

 

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 110

int k, len;
char str[MAX];
int num[MAX], test[MAX];
int for_mod[MAX][10];
int remember[MAX][10010];

void init()
{
    int i,j;
    for(i = 0; i< 10; ++i)
      for_mod[0][i] = i % k;
    for(i = 1; i< len; ++i)
    {
      for(j = 0; j < 10; ++j)
         for_mod[i][j] = (10*for_mod[i-1][j]) % k;
    }
   memset(remember,0,sizeof(remember[0])*len);
}

bool dfs(int left,int index,int mod)
{
    int t;
    int i,j;
    if(mod ==0)
    {
      for(i = len-1; i >= 0; --i)
         printf("%d",test[i]);
      printf("\n");
      return true;
    }
   if(remember[left][mod] > index ||left == 0)
      return false;
      
    for(i =index; i >= 0; --i)
    {
      for(j = 0; j < num[i]; ++j)
      {
         if(i == len-1 &&j == 0)
            continue;
         t = for_mod[i][j] + mod -for_mod[i][num[i]];
         t %= k;
         if(t < 0) t += k;
         test[i] = j;
         if(dfs(left-1,i-1,t))
            return true;
      }
      test[i] = num[i];
    }
    
    for(i = 0; i<= index; ++i)
    {
      for(j = num[i]+1; j < 10;++j)
      {
         t = for_mod[i][j] + mod -for_mod[i][num[i]];
         t %= k;
         if(t < 0) t += k;
         test[i] = j;
         if(dfs(left-1,i-1,t))
            return true;
      }
      test[i] = num[i];
    }
   remember[left][mod] = index+1;
    returnfalse;
}

int main()
{
    int i,j;
    intmod;
//   freopen("input.txt","r",stdin);
   while(scanf("%s",str) != EOF)
    {
      scanf("%d",&k);
      len = strlen(str);
      mod = 0;
      init();
      
      for(i = 0; i < len; ++i)
      {
         num[i] = test[i] = str[len-i-1]-'0';
         mod += for_mod[i][num[i]];
         mod %= k;
      }
      
      for(i = 0; ; ++i)
      {
         if(dfs(i,len-1,mod))
            break;
      }
    }
    return0;
}

 

0 0
原创粉丝点击