• 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值更小。



    具体看代码。
  • 相关阅读:
    VIM于换行EOL的思考
    wp7给图片和按钮添加背景图片
    wp7打开加速度传感器
    java值传递、引用传递
    keychron k1长时间不使用蓝牙,蓝牙连接不上解决方案
    IE浏览器切换64位和32位
    文件和注册表的重定向解决方法
    Windows C++遍历所有进程的命令行
    c++ fstream open 失败原因
    解析wrk压测工具
  • 原文地址:https://www.cnblogs.com/ouyangduoduo/p/3197397.html
Copyright © 2020-2023  润新知