dp[i][j][d][k]表示从前i个选j个对d取余为k的种类数
这题要注意的是num可能为负,首先要将其变为正数
还有。。。要用longlong
AC代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
long long dp[220][12][22][22];
long long N, Q, D, M;
long long num[220][22];
void init(){
for( long long i = 1; i <= N; i++ ){
for( long long j = 1; j <= 20; j++ ){
num[i][j] = ( num[i][0] + j * 1000000000000 ) % j;
}
}
memset( dp, 0, sizeof( dp ) );
for( long long i = 0; i <= 20; i++ ){
dp[0][0][i][0] = 1;
}
for( long long i = 0; i < N; i++ ){
for( long long j = 0; j <= i && j <= 10; j++ ){
for( long long d = 1; d <= 20; d++ ){
for( long long k = 0; k < d; k++ ){
dp[i+1][j][d][k] += dp[i][j][d][k];
dp[i+1][j+1][d][(k+num[i+1][d])%d] += dp[i][j][d][k];
}
}
}
}
}
int main(){
long long T, Case = 1;
scanf( "%lld", &T );
while( T-- ){
scanf( "%lld%lld", &N, &Q );
for( long long i = 1; i <= N; i++ ){
scanf( "%lld", &num[i][0] );
}
init();
printf( "Case %lld:\n", Case++ );
for( long long i = 0; i < Q; i++ ){
int temp1, temp2;
scanf( "%d%d", &temp1, &temp2 );
printf( "%lld\n", dp[N][temp2][temp1][0] );
}
}
return 0;
}