zoukankan      html  css  js  c++  java
  • poj 3373 Changing Digits

    Description

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

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

    Input

    There are multiple test cases for the input. Each test case consists of two lines, which contains n(1≤n≤10100) and k(1≤k≤104kn) for each line. Both n and k will not contain leading zeros.

    Output

    Output one line for each test case containing the desired number m.

    Sample Input

    2
    2
    619103
    3219

    Sample Output

    2
    119103
      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <string>
      5 using namespace std;
      6 char str[101];
      7 int num1[101],num2[101];
      8 int flag[101][10005];
      9 int k;
     10 int len;
     11 int getY(int num[])
     12 {
     13     int j;
     14     int m=0;
     15     for(j=len-1;j>=0;j--)
     16     {
     17         m=(m*10+num[j])%k;
     18     }
     19     return m;
     20 }
     21 
     22 void init()
     23 {
     24     int i;
     25     for(i=0;i<len;i++)
     26     {
     27         num1[i] = num2[i] = str[len-1-i]-'0';
     28     }
     29     memset(flag,0,sizeof(flag));
     30 }
     31 bool dfs(int pos,int num,int m)
     32 {
     33     int i,j;
     34     if(m==0)
     35     {
     36         for(i=len-1;i>=0;i--)printf("%d",num1[i]);
     37         printf("
    ");
     38         return true;
     39     }
     40 
     41     if(pos<0 || num<=flag[pos][m] || num==0)
     42     {
     43         return false;
     44     }
     45     for(i=pos;i>=0;i--)
     46     {
     47         for(j=0;j<num2[i];j++)
     48         {
     49             if(i==len-1 && j==0)
     50             {
     51                 continue;//±ÜÃâǰµ¼0;
     52             }
     53             num1[i]=j;
     54             int a=getY(num1);
     55             if(dfs(i-1,num-1,a))
     56             {
     57                 return true;
     58             }
     59         }
     60         num1[i]=num2[i];
     61     }
     62     for(i=0;i<=pos;i++)
     63     {
     64         for(j=num2[i]+1;j<=9;j++)
     65         {
     66             if(j==0 && i==len-1)
     67             {
     68                 continue;
     69             }
     70             num1[i]=j;
     71             int a=getY(num1);
     72             if(dfs(i-1,num-1,a))
     73             {
     74                 return true;
     75             }
     76         }
     77         num1[i]=num2[i];
     78     }
     79     flag[pos][m]=num;
     80     return false;
     81 }
     82 void solve()
     83 {
     84     int i;
     85     int m=getY(num1);
     86     for(i=1;i<=5;i++)
     87     {
     88         if(dfs(len-1,i,m))return;
     89     }
     90 }
     91 int main()
     92 {
     93     while(~scanf("%s%d",str,&k))
     94     {
     95         len = strlen(str);
     96         init();
     97         solve();
     98 
     99     }
    100 }
    View Code

    此题属于记忆化深搜,再加点技巧。

    题目大意:

    给出2个整数n(n<10^100)和k(k<10000),求满足以下条件的整数m

     1、m与n位数相同
     2、m能被k整除
     3、满足以上两点时,m和n在相同位置的地方,数字不同的个数最少

     4、满足以上三点时,m值最小

    解题步骤:
    一、解决条件1很简单;
    二、判断能否被k整除,使用同余模公式,解决大数能否被整除问题;
    三、尽可能改变少的数字来满足条件

    bool DFS(int pos,int num,int m);

    传参有3个:pos,num,m

    pos:当前搜索区间为[0,pos]

    num:在区间[0,pos]中剩余 允许改变的数字的个数,个数从1个到len(n)个枚举,保证搜索到解时,n与m在相同位置处不同数字的个数是最少的(条件3)。

    m:当前数字串m对k求模的值,初始化为a。

    (1)搜索时先搜索比n小的数字,此时为了搜索到的解m是最小的,应该从区间[0,pos]的第pos位开始向第0位搜索,因为在相同num情况下,把高位数字变小所得到的m值更小。

    (2)当(1)无解时,搜索比n大的数字,此时为了搜索到的解m是最小的,应该从区间[0,pos]的第0位开始向第pos位搜索,因为在相同num情况下,把低位数字变大所得到的m值更小。



    具体看代码。
  • 相关阅读:
    219. Contains Duplicate II
    189. Rotate Array
    169. Majority Element
    122. Best Time to Buy and Sell Stock II
    121. Best Time to Buy and Sell Stock
    119. Pascal's Triangle II
    118. Pascal's Triangle
    88. Merge Sorted Array
    53. Maximum Subarray
    CodeForces 359D Pair of Numbers (暴力)
  • 原文地址:https://www.cnblogs.com/ouyangduoduo/p/3197397.html
Copyright © 2011-2022 走看看