HDU 4669 Mutiples on a circle 动态规划

参考了官方题解给的方法:

对于处理循环,官方给了一种很巧妙的方法:

#include <cstdio>
#include <cstring>
#include <cstdlib>

#define LL long long int

const int MAXN = 50010;
const int MAXMOD = 210;

int N, K;
int dp[MAXN][MAXMOD];
int val[MAXN];
int fac[MAXN << 2];
int len[1010];

void init()
{
    for ( int i = 0; i < 10; ++i ) len[i] = 1;
    for ( int i = 10; i < 100; ++i ) len[i] = 2;
    for ( int i = 100; i < 1000; ++i ) len[i] = 3;
    for ( int i = 1000; i < 1010; ++i ) len[i] = 4;
    return;
}

void GetFac()
{
    fac[0] = 1;
    int lenn = (N << 2);
    for ( int i = 1; i < lenn; ++i )
        fac[i] = ( fac[i - 1] * 10 ) % K;
    return;
}

int main()
{
    //freopen( "1004.in", "r", stdin );
    //freopen( "ss.out", "w", stdout );
    init();
    while ( ~scanf("%d%d", &N, &K ) )
    {
        for ( int i = 0; i < N; ++i )
            scanf( "%d", &val[i] );
        GetFac();

        val[N] = val[0];
        int sum = 0;
        int totL = 0;

        //不要用memset,否则会超时
        for ( int i = 0; i <= N; ++i )
            for ( int j = 0; j <= K; ++j )
                dp[i][j] = 0;

        for ( int i = N; i > 0; --i )
        {
            sum = ( val[i] * fac[totL] + sum ) % K;
            totL += len[ val[i] ];
            ++dp[0][sum];
        }

        LL ans = dp[0][0];
        for ( int i = 1; i < N; ++i )
        {
            for ( int j = 0; j < K; ++j )
                dp[i][ ( j * fac[ len[ val[i] ] ] + val[i] ) % K ] += dp[i - 1][j];
            sum = ( sum * fac[ len[ val[i] ] ] + val[i] ) % K;
            --dp[i][sum];
            ++dp[i][ val[i]%K ];
            sum = ( ( sum - val[i] * fac[totL] ) % K + K ) % K;
            ans += dp[i][0];
        }

        printf( "%I64d
", ans );
    }
    return 0;
}
原文地址:https://www.cnblogs.com/GBRgbr/p/3256584.html