参考了官方题解给的方法:
对于处理循环,官方给了一种很巧妙的方法:
#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; }