Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 3485 | Accepted: 1136 |
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
题目链接:http://poj.org/problem?id=3373
好吧,这个题我搜的题解,想到了数位DP,但是真的没想出来怎么敲,归到了记忆化搜索,又不知道怎么写dfs,还是太菜了,看的大神的博客
http://blog.csdn.net/lyy289065406/article/details/6698787/
大神说的很仔细,但我还是看了好久,这个题存着,过两天回来再练!
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#define maxn 103
#define mk 10003
using namespace std;
int len,k,n[maxn],mod[maxn][10];
int m[maxn],flag[maxn][mk];
char num[maxn];
void Init_mod(){
for(int i=0;i<=9;i++){
mod[0][i]=i%k;
for(int i=1;i<len;i++){
for(int j=0;j<=9;j++){
mod[i][j]=(mod[i-1][j]*10)%k;
}
}
}
}
int dfs(int pos,int restnum,int m_modk){
if(!m_modk)
return 1;
if(!restnum||pos<0)
return 0;
if(restnum<=flag[pos][m_modk])
return 0;
for(int i=pos;i>-1;i--){
for(int j=0;j<n[i];j++){
if(i==len-1&&!j){
continue;
}
int res=(m_modk-(mod[i][n[i]]-mod[i][j])+k)%k;
m[i]=j;
if(dfs(i-1,restnum-1,res))
return 1;
m[i]=n[i];
}
}
for(int i=0;i<=pos;i++){
for(int j=n[i]+1;j<10;j++){
int res=(m_modk+(mod[i][j]-mod[i][n[i]])+k)%k;
m[i]=j;
if(dfs(i-1,restnum-1,res))
return 1;
m[i]=n[i];
}
}
flag[pos][m_modk]=restnum;
return 0;
}
int main(){
while(~scanf("%s%d",num,&k)){
int n_modk=0;
len=strlen(num);
Init_mod();
for(int i=0;i<len;i++){
n[i]=num[len-1-i]-'0';
m[i]=n[i];
n_modk=(n_modk+mod[i][n[i]])%k;
}
memset(flag,0,sizeof(flag));
for(int i=1;i<=len;i++){
if(dfs(len-1,i,n_modk))
break;
}
for(int i=len-1;i>-1;i--){
printf("%d",m[i]);
}
cout<<endl;
}
return 0;
}