状态压缩,第一维记录哪些位置的数字用过,第二维记录当前状态余数为多少。在第三层循环时,若数字x前面已经用过,则不用再次计数,因为没有区别,如果计入则最后需要除以每种数的阶乘。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
LL dp[1 << 18][103];
int v[15];
char a[20];
int m;
int main(){
scanf("%s%d", a, &m);
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
int len = strlen(a);
for(int i = 0; i < (1 << len); i++){
for(int j = 0; j < m; j++){
memset(v, 0, sizeof(v));
for(int k = 0; k < len; k++){
int x = a[k] - '0';
if(i & (1 << k))continue;
if(i == 0 && x == 0)continue;
if(v[x])continue;
v[x] = 1;
dp[i | (1 << k)][(j * 10 + x) % m] += dp[i][j];
}
}
}
printf("%I64d\n", dp[(1 << len) - 1][0]);
return 0;
}