难得能自己想出来一道蓝色的(DP)
设f[i][j]
表示前(i)个数表示出取模结果为(j)时的最小(k)值,sum[i][j]
表示区间([i,j])所表示数值取模后的结果,显然,转移为:
f[i][(k * sum[j+1][i])] = min(f[j][k] + 1, f[i][(k * sum[j+1][i])])
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define LL long long
LL read() {
LL k = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9')
k = k * 10 + c - 48, c = getchar();
return k * f;
}
int f[2010][60], sum[2010][2010], m, n;
char s[2010];
int main() {
scanf("%s", s+1); m = read(), n = strlen(s+1);
for(int i = 1; i <= n; ++i)
for(int j = i; j <= n; ++j)
sum[i][j] = (sum[i][j-1] * 10 + s[j] - 48) % m;
memset(f, 127, sizeof(f));
for(int i = 1; i <= n; ++i) f[i][sum[1][i]] = 0;
for(int i = 2; i <= n; ++i) {
for(int j = 1; j < i; ++j) {
for(int k = 0; k < m; ++k) {
int p = (k * sum[j+1][i]) % m;
f[i][p] = min(f[j][k] + 1, f[i][p]);
}
}
}
for(int i = 0; i < m; ++i)
if(f[n][i] <= 10000) {
printf("%d %d ", i, f[n][i]);
break;
}
for(int i = m-1; i; --i)
if(f[n][i] <= 10000) {
printf("%d %d ", i, f[n][i]);
break;
}
return 0;
}