NOIガイド2010増加ルーンワード

トピックポータル

めったにあなたが青のうち希望することはできません\(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;
}

おすすめ

転載: www.cnblogs.com/morslin/p/11855386.html