[CF401D] Roman and Numbers - 状压dp
Description
将n(n<=10^18)的各位数字重新排列(不允许有前导零) 求 可以构造几个mod m等于0的数字
Solution
状压 dp,从高位往低位走,枚举下一位选哪个数字,设 (f[s][k]) 表示选取了 s 子集的数字,余数为 k
#include <bits/stdc++.h>
using namespace std;
#define int long long
int f[1 << 18][105], n, a[19], cnt[10], m;
signed main()
{
ios::sync_with_stdio(false);
string str;
cin >> str;
int len = str.length();
for (int i = 0; i < len; i++)
a[i] = str[i] - '0';
cin >> m;
f[0][0] = 1;
for (int i = 0; i < 1 << len; i++)
for (int j = 0; j < len; j++)
if ((i & (1 << j)) == 0 && (i > 0 || a[j] > 0))
{
for (int k = 0; k < m; k++)
f[i | (1 << j)][(k * 10 + a[j]) % m] += f[i][k];
}
int ans = 1;
for (int i = 0; i < len; i++)
ans *= ++cnt[a[i]];
cout << f[(1 << len) - 1][0] / ans << endl;
}