看到题目首先想到了数位dp
观察发现,从低位向高位很好推.
令fijkg表示第i个位置,进位值为j 数位和为k 乘d后数位和为g得情况是否成立...
稍微算一算100 * 10 * 1000 * 1000肯定爆掉了...
考虑优化,令fijk表示能凑成进位值为i 数位和为j 乘d后数位和为k最短得长度...
那么这样复杂度就在1000w 可以接受...
因为要保证得到得数是最小得情况,那么只能从高位到低位枚举。
而且每次选出来的值均对原本乘积和得值有影响,那么还要更新一下...
理论上来说不是很难,但是本沙茶还是写了一天...
c++代码如下:
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctime>
#include <cstring>
#include <iostream>
#include <algorithm>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define lowbit(x) x&(-x)
#define PA pair<int, int>
#define MK make_pair
#define rep(i,x,y) for(register int i = x; i <= y; ++ i)
#define repd(i,x,y) for(register int i = x; i >= y; -- i)
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
x = 0;char c;int sign = 1;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
int n,s1,s2,d;
int f[10][901][910],nw[101],t[101];
struct Str { int lst,num1,num2; };
inline void bfs()
{
queue<Str>q;
q.push((Str){0,0,0});
f[0][0][0] = 0;
while(!q.empty())
{
Str a = q.front();q.pop();
rep(i,0,9) if(a.num1 + i <= s1 && a.num2 + (i*d + a.lst)%10 <= s2 && f[(a.lst + i*d)/10][a.num1 + i][a.num2 + (i*d + a.lst)%10] > f[a.lst][a.num1][a.num2] + 1){
f[(a.lst + i*d)/10][a.num1 + i][a.num2 + (i*d + a.lst)%10] = f[a.lst][a.num1][a.num2] + 1;
q.push((Str){(a.lst + i*d)/10,a.num1 + i,a.num2 + (i*d + a.lst)%10});
}
}
}
void get(int now,int s1,int p)
{
if(now == n + 1) exit(0);
rep(k,0,9)
{
rep(j,0,9)
{
int q = now,z = p;
t[now] = k*d + j;
while(t[q] + nw[q] >= 10)
{
t[q - 1] = (t[q] + nw[q]) / 10;
t[q] = (t[q] + nw[q]) %10;
z += t[q] - nw[q];
--q;
}
z += t[q];
if(s1 >= k && s2 >= z && f[j][s1 - k][s2 - z] + now <= n)
{
q = now;
nw[q] = k*d; p += nw[q];
while(nw[q] >= 10)
{
p -= nw[q - 1] + nw[q];
nw[q - 1] += nw[q]/10;nw[q] %= 10;
p += nw[q - 1] + nw[q];
--q;
}
printf("%d",k);
get(now + 1,s1 - k,p);
}
}
}
}
int main()
{
memset(f,0x3f,sizeof f);
read(n);read(s1);read(s2);read(d);
bfs();
int z = 0;
rep(i,1,9)
{
rep(j,0,9)
if(s1 >= i && s2 - (i*d + j)%10 - (i*d + j)/10 >= 0 && f[j][s1 - i][s2 - (i*d + j)%10 - (i*d + j)/10] < n)
{
z = i;
nw[1] = (i * d)%10;
nw[0] = (i * d)/10;
break;
}
if(z) break;
}
if(!z) return puts("-1");
cout << z;
get(2,s1 - z,nw[1] + nw[0]);
return 0;
}