poj 3373


Changing Digits

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 2960   Accepted: 952

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

Source

POJ Monthly--2007.09.09, Rainer

参考(很详细):http://blog.csdn.net/lyy289065406/article/details/6698787/
AC代码:
<pre name="code" class="cpp">#include<iostream>
#include<cstring>
using namespace std;
char s[105];
int n[105],m[105];
int k,n_mod;
int mod[105][10],f[105][10005];
int DFS(int pos,int res_num,int m_mod){
    if(m_mod==0)
        return 1;
    if(pos<0 || res_num==0)
        return 0;
    if(res_num<=f[pos][m_mod])
        return 0;
    for(int i=pos;i>=0;i--){
        for(int j=0;j<n[i];j++){
            if(i==strlen(s)-1 && j==0)
                continue;
            int res=(m_mod-(mod[i][m[i]]-mod[i][j])+k)%k;
            int tmp=m[i];
            m[i]=j;
            if(DFS(pos-1,res_num-1,res))
                return 1;
            m[i]=tmp;
        }
    }

    for(int i=0;i<=pos;i++){
        for(int j=n[i]+1;j<=9;j++){
            if(i==strlen(s)-1 && j==0)
                continue;
            int res=(m_mod-(mod[i][m[i]]-mod[i][j]))%k;
            int tmp=m[i];
            m[i]=j;
            if(DFS(pos-1,res_num-1,res))
                return 1;
            m[i]=tmp;
        }
    }
    f[pos][m_mod]=res_num;
    return 0;
}
int main(){
    while(cin>>s>>k){
        for(int i=0;i<strlen(s);i++)
            n[i]=m[i]=s[strlen(s)-1-i]-'0';

        for(int i=0;i<=9;i++)
            mod[0][i]=i%k;
        for(int i=1;i<strlen(s);i++)
            for(int j=0;j<=9;j++)
                mod[i][j]=(mod[i-1][j]*10)%k;

        n_mod=0;
        for(int i=0;i<strlen(s);i++){
            n_mod=(n_mod+mod[i][m[i]])%k;
        }
        memset(f,0,sizeof(f));

        for(int i=0;i<=strlen(s);i++){
            if(DFS(strlen(s)-1,i,n_mod))
                break;
        }
        for(int i=strlen(s)-1;i>=0;i--)
            cout<<m[i];
        cout<<endl;
    }
    return 0;
}

poj 3373

时间: 2024-11-05 11:01:44

poj 3373的相关文章

POJ 3373 Changing Digits

题目大意: 给出一个数n,求m,使得m的长度和n相等,能被k整除.有多个数符合条件输出与n在每位数字上改变次数最小的.改变次数相同的输出大小最小的.  共有两种解法:DP解法,记忆化搜索的算法. 以后会更新记忆化搜索. 1.DP解法: 解题思路: DP[i][j]表示数n的前i位除以k余j最小改变几位. DP[len][0]就表示数n被k整除最小改变几位. 根据这个关系从后向前遍历DP数组可以找出所有满足条件的数的路径. 再根据关系从前往后输出.  下面是代码: #include <stdio.

POJ 3373 Changing Digits 好蛋疼的DP

一开始写的高位往低位递推,发现这样有些时候保证不了第四条要求.于是又开始写高位往低位的记忆化搜索,又发现传参什么的蛋疼的要死.然后又发现高位开始的记忆化搜索就是从低位往高位的递推呀,遂过之. dp[i][j]记录在i位 且 余数为j时的最优解情况. dp[i][j].next表示当前的最优解是由哪一种状态转移过来的. 代码又写锉了.. #include <algorithm> #include <iostream> #include <cstring> #include

POJ题目分类推荐 (很好很有层次感)

著名题单,最初来源不详.直接来源:http://blog.csdn.net/a1dark/article/details/11714009 OJ上的一些水题(可用来练手和增加自信) (POJ 3299,POJ 2159,POJ 2739,POJ 1083,POJ 2262,POJ 1503,POJ 3006,POJ 2255,POJ 3094) 初期: 一.基本算法: 枚举. (POJ 1753,POJ 2965) 贪心(POJ 1328,POJ 2109,POJ 2586) 递归和分治法. 递

POJ 刷题指南

OJ上的一些水题(可用来练手和增加自信) (POJ 3299,POJ 2159,POJ 2739,POJ 1083,POJ 2262,POJ 1503,POJ 3006,POJ 2255,POJ 3094) 初期: 一.基本算法: 枚举. (POJ 1753,POJ 2965) 贪心(POJ 1328,POJ 2109,POJ 2586) 递归和分治法. 递推. 构造法.(POJ 3295) 模拟法.(POJ 1068,POJ 2632,POJ 1573,POJ 2993,POJ 2996) 二

POJ - 3186 Treats for the Cows (区间DP)

题目链接:http://poj.org/problem?id=3186 题意:给定一组序列,取n次,每次可以取序列最前面的数或最后面的数,第n次出来就乘n,然后求和的最大值. 题解:用dp[i][j]表示i~j区间和的最大值,然后根据这个状态可以从删前和删后转移过来,推出状态转移方程: dp[i][j]=max(dp[i+1][j]+value[i]*k,dp[i][j-1]+value[j]*k) 1 #include <iostream> 2 #include <algorithm&

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

POJ——T2271 Guardian of Decency

http://poj.org/problem?id=2771 Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5932   Accepted: 2463 Description Frank N. Stein is a very conservative high-school teacher. He wants to take some of his students on an excursion, but he is

POJ——T2446 Chessboard

http://poj.org/problem?id=2446 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18560   Accepted: 5857 Description Alice and Bob often play games on chessboard. One day, Alice draws a board with size M * N. She wants Bob to use a lot of c

poj 1088 滑雪 DP(dfs的记忆化搜索)

题目地址:http://poj.org/problem?id=1088 题目大意:给你一个m*n的矩阵 如果其中一个点高于另一个点 那么就可以从高点向下滑 直到没有可以下滑的时候 就得到一条下滑路径 求最大的下滑路径 分析:因为只能从高峰滑到低峰,无后效性,所以每个点都可以找到自己的最长下滑距离(只与自己高度有关).记忆每个点的最长下滑距离,当有另一个点的下滑路径遇到这个点的时候,直接加上这个点的最长下滑距离. dp递推式是,dp[x][y] = max(dp[x][y],dp[x+1][y]+