您的位置:首页 > 其它

poj 3373 Changing Digits

2013-07-18 09:01 621 查看
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:

m contains no leading zeros and has the same length as n (We consider zero itself a one-digit integer without leading zeros.)

m is divisible by k

among all numbers satisfying properties 1 and 2, m would be the one with least number of digits different from n

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≤104, k≤n) 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


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
using namespace std;
char str[101];
int num1[101],num2[101];
int flag[101][10005];
int k;
int len;
int getY(int num[])
{
int j;
int m=0;
for(j=len-1;j>=0;j--)
{
m=(m*10+num[j])%k;
}
return m;
}

void init()
{
int i;
for(i=0;i<len;i++)
{
num1[i] = num2[i] = str[len-1-i]-'0';
}
memset(flag,0,sizeof(flag));
}
bool dfs(int pos,int num,int m)
{
int i,j;
if(m==0)
{
for(i=len-1;i>=0;i--)printf("%d",num1[i]);
printf("\n");
return true;
}

if(pos<0 || num<=flag[pos][m] || num==0)
{
return false;
}
for(i=pos;i>=0;i--)
{
for(j=0;j<num2[i];j++)
{
if(i==len-1 && j==0)
{
continue;//±ÜÃâÇ°µ¼0;
}
num1[i]=j;
int a=getY(num1);
if(dfs(i-1,num-1,a))
{
return true;
}
}
num1[i]=num2[i];
}
for(i=0;i<=pos;i++)
{
for(j=num2[i]+1;j<=9;j++)
{
if(j==0 && i==len-1)
{
continue;
}
num1[i]=j;
int a=getY(num1);
if(dfs(i-1,num-1,a))
{
return true;
}
}
num1[i]=num2[i];
}
flag[pos][m]=num;
return false;
}
void solve()
{
int i;
int m=getY(num1);
for(i=1;i<=5;i++)
{
if(dfs(len-1,i,m))return;
}
}
int main()
{
while(~scanf("%s%d",str,&k))
{
len = strlen(str);
init();
solve();

}
}


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

具体看代码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: