传送门](http://codeforces.com/group/xrTA2IaQje/contest/258354)
题意:给一个大数(长度小于1000)和一个n
但是这个大数的有些位用?表示不确定,现在要把所有?填上后使他是n的倍数,并且最小。
思路:简单DP
dp[i][j]表示使第i位模数的为j的最小值,然后模拟就可以了
要注意的是我们要从后往前dp!!!这样在还原的时候才能保证字典序最小
因为如果从前往后dp,我们在还原答案的时候是从后往前还原的。这样的话会优先让低位最小而不是有限让高位最小

#include<bits/stdc++.h>
using namespace std;
typedef long long L;
char s[2001];
L dp[2001][2001],n,l;
L val[2001];
L qp(L x,L y,L mod)
{
    L ans=1;
    while(y){
        if(y&1) ans=ans*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return ans;
}
int main()
{
    cin>>s+1>>n;
    l=strlen(s+1);
    for(int i=l;i>=1;i--){
        if(s[i]=='?') val[i]=qp(10,l-i,n);
        else val[i]=(s[i]-'0')%n*qp(10,l-i,n)%n;
    }
 
    for(int i=1;i<=l+1;i++) for(int j=0;j<n;j++) dp[i][j]=INT_MAX;
    dp[l+1][0]=0;
    for(int i=l;i>=1;i--){
        if(s[i]=='?'){
            for(int j=0;j<=9;j++){
                if(i==1&&j==0) continue;
                for(int k=0;k<n;k++){
                    if(dp[i+1][k]!=INT_MAX){
                        dp[i][(k+val[i]*j%n)%n]=min(dp[i][(k+val[i]*j%n)%n],j*1ll);
                    }
                }
            }
        }
        else {
            int c=s[i]-'0';
            for(int k=0;k<n;k++){
                if(dp[i+1][k]!=INT_MAX){
                    dp[i][(k+val[i])%n]=c;
                }
            }
        }
    }
 
    if(dp[1][0]!=INT_MAX) {
        int now=0;
        for(int i=1;i<=l;i++) {
            printf("%lld",dp[i][now]);
            int w=dp[i][now]*qp(10,l-i,n)%n;
            now=((now-w)%n+n)%n;
 
        }
        printf("\n");
    }
    else printf("*\n");
}