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:
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 Source
POJ Monthly--2007.09.09, Rainer
|
提示
题意:给出两个正整数n,k(1<=k<=10^4,1<=n<=10^100,k<=n),根据以下规则求出m:
1.n的位数和m相同。
2.m可以被k整除。次
3.优先考虑尽可能然n和m的每一位数相同。
4.在满足3个条件的情况下尽可能的使m的为最小。
之后输出m。
思路:
实际上对于任何一个n都有至少改变len(k)次就可得到答案。因为我们在n中改变len(k)次可以得到10^len(k)个数,其中最坏的情况就是把n的后len(k)位都给改了。(这里的len(k)为k的位数)
当k=10000时,我们可知把后四位全改为0即可,因此n可改变的位数最大为4,可做。还需要加上搜索标记,当前状态是否已经搜过。
刷题刷到现在应该没有对这题直接上double或long long的吧。。。
示例程序
Source Code
Problem: 3373 Code Length: 1134B
Memory: 20168K Time: 1157MS
Language: GCC Result: Accepted
#include <stdio.h>
#include <string.h>
char s[101],ans[101],ch[101]; //s[]为初始的n,ans[]为m,ch[]为搜索时中转的变量
int k,v[5][101][10000],len,step; //len为n的位数,step为最多改变的位数个数
void dfs(int change,int deep,int sum) //change为当前状态所改变的位数个数,deep为当前个数,sum为进行取模的过程
{
int i;
if(deep==len)
{
if(change<step&&sum==0) //我们对每一位数都是从小到大开始枚举的,要保证改变位数要小于之前的
{
step=change;
strcpy(ans,ch);
}
return;
}
if(change>=step)
{
return;
}
if(v[change][deep][sum]==1)
{
return;
}
v[change][deep][sum]=1; //当前状态记录,防止重复遍历
for(i=0;9>=i;i++)
{
ch[deep]='0'+i;
if(ch[deep]!=s[deep])
{
dfs(change+1,deep+1,(sum*10+i)%k);
}
else
{
dfs(change,deep+1,(sum*10+i)%k);
}
}
}
int main()
{
int i;
while(scanf("%s",s)!=EOF)
{
scanf("%d",&k);
len=strlen(s);
strcpy(ch,s);
step=5;
memset(v,0,sizeof(v));
for(i=1;9>=i;i++)
{
ch[0]='0'+i;
if(ch[0]!=s[0])
{
dfs(1,1,i%k);
}
else
{
dfs(0,1,i%k);
}
}
printf("%s\n",ans);
}
return 0;
}