您的位置:首页 > Web前端 > JavaScript

[BZOJ4467] [JSOI2013]数字理论

2016-04-05 16:25 1021 查看
题目相当于要求一个数x,满足:

1. D∗10K−1≤x<D∗10K

2. x mod D=0

3. digit(x)=P //digit(x)是x的各个数位数字之和

4. digit(x/D)=S

考虑进行数位DP

bool dp[len][sum1][sum2][res]意思是,有一个数W,digit(W div D)=sum1,digit(W)=sum2,W mod D=res,能否通过在W的末尾加len位数字使得符合要求

显然边界为dp[0][S][P][0]=1 dp[0][其他]=0

转移为dp[len][sum1][sum2][res]=OR9next=0dp[len−1][sum1+(res∗10+next) div D][sum2+next][(res∗10+next) modD]

找方案时贪心地从高位向地位,在DP数组上爬下去^..^

然而这样状态数是O(K*S*P*D),显然会MLE+TLE

怎么办呢?对!常数优化!

我们可以发现,sum1和res确定时,sum2 mod 9是确定的,于是时间和内存的常数就除了9,然后又有好多无效的状态,如len∗9+sum1<S或len∗9+sum2<P,虽然理论时间复杂度还是O(K*S*P*D*10),大约是90亿,但大多数都是无效状态,拜张爷爷的剪枝技巧所赐,便轻松过去了

#include <cstdio>
#include <assert.h>
int K, S, P, D;
bool dp[100][901][102][9];
int main()
{
scanf("%d%d%d%d", &K, &S, &P, &D);
if (S > K * 9 || P > K * 9)
return puts("-1"), 0;
if (S * D % 9 != P % 9)
return puts("-1"), 0;
dp[0][S][P / 9][0] = 1;
for (int i = 1; i < K; i++)
{
int S_low = S - i * 9, P_low = P - i * 9, MODnine;
if (S_low < 0)
S_low = 0;
if (P_low < 0)
P_low = 0;
for (int j = S_low; j <= S; j++)
{
bool (*DP)[9] = dp[i][j];
for (int l = 0; l < D; l++)
{
MODnine = (j * D + l) % 9;
for (int k = P_low / 9, realk = k * 9 + MODnine; realk <= P; k++, realk += 9)
for (int di = 0; !DP[k][l] && di < 10; di++)
if (dp[i - 1][j + (l * 10 + di) / D][(realk + di) / 9][(l * 10 + di) % D])
DP[k][l] = 1;
}
}
}
int head = D;
while (head < 10 * D && !dp[K - 1][head / D][(head / 10 + head % 10) / 9][head % D])
head++;
if (head == 10 * D)
puts("-1");
else
{
int res = head % D;
putchar(head / D + 48);
int I = K - 1, J = head / D, K = head / 10 + head % 10, L = head % D, di;
int newI, newJ, newK, newL;
while (I)
{
for (di = 0; !dp[I - 1][J + (L * 10 + di) / D][(K + di) / 9][(L * 10 + di) % D]; di++)
"Nothing to do..";
putchar((res * 10 + di) / D + 48);
res = (res * 10 + di) % D;
newI = I - 1, newJ = J + (L * 10 + di) / D, newK = K + di, newL = (L * 10 + di) % D;
I = newI, J = newJ, K = newK, L = newL;
}
assert(res == 0);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: