poj 3373 数论常识(数位dp)

题目:http://poj.org/problem?id=3373
题意:

给出2个整数n(n<10^100)和k(k<10000),求满足以下条件的整数m
1、m与n位数相同
2、m能被k整除
3、满足以上两点时,m和n在相同位置的地方,数字不同的个数最少
4、满足以上三点时,m值最小

分析:

这题很容易想到怎么做:
dp[i][j][num]表示前i位数构成的数是j,改变了num次,记忆化搜索就好。
但是num最大是多少呢?
假设k的位数是m,那么n最多只要改变m为位就可以%k==0了!因为n的m位之前的数%k可以得到一个数X,后m位变成k-X就行了!
所以k最大为10000,最多改变5位就行!

代码:

const int N = 1e4 + 9;
int d[110][N][6], n, k,minn;
char s[110],ans[110];
void dfs(int pos,int pre,int num) {
    if(pos==n) {
        if(num0) {
            minn=num;
            strcpy(ans,s);
        }
        return;
    } else if(numif(!d[pos][pre][num]) {
            d[pos][pre][num]=1;
            char t=s[pos];
            for(int i=0; i<=9; i++) {
                if(pos==0&&i==0)continue;
                s[pos]=i+'0';
                dfs(pos+1,(pre*10+i)%k,num+(i!=t-'0'));

            }
            s[pos]=t;
        }
    }
}
int main() {
    //freopen ("f.txt", "r", stdin);
    while (~scanf ("%s %d", s, &k) ) {
        n = strlen (s);
        memset(d,0,sizeof(d));
        minn=6;
        dfs (0, 0, 0);
        printf("%s\n",ans);
    }
    return 0;
}

你可能感兴趣的:(数位dp,数论——基本定理)