- 要输出方案,很容易想到把方案放到dp值。 但这样我们dp需要记录余数,还要给数字排列
- 看到D的范围范围会想到状压,让dp的一维表示D个数字的使用情况。这样就可以用状压来得到数字的排列。 比如: 状压的 1000 就是第一个数字放到最高位,0100 是第二个数字放到最高位。
- 时间复杂度是 D * K * (1 << D), 需要稍微剪枝一下
#include<bits/stdc++.h>
//#include <bits/extc++.h>
using namespace std;
// using namespace __gnu_cxx;
// using namespace __gnu_pbds;
#define IOS ios::sync_with_stdio(false) ,cin.tie(0), cout.tie(0);
//#pragma GCC optimize(3,"Ofast","inline")
#define ll long long
#define li __int128_t
//#define int long long
const int N = 1e5 + 5;
const int M = 1e6 + 5;
const int mod = 1e9 + 7;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
ll f[205][1 << 16];
int a[205];
int main () {
IOS
memset(f, -1, sizeof f);
f[0][0] = 0;
int n, K; cin >> n >> K;
for ( int i = 0; i < n; ++ i ) cin >> a[i];
for ( int i = 0; i < 1 << n; ++ i ) {
for ( int j = 0; j < K; ++ j ) {
if(f[j][i] == -1) continue;
for ( int k = 0; k < n; ++ k ) {
if(i >> k & 1) continue;
int nei = i | (1 << k), nej = (j * 10 + a[k] ) % K;
f[ nej ][ nei ] = max( f[j][i] * 10 + a[k], f[ nej ][ nei ] ) ;
}
}
}
for ( int i = K - 1; i >= 0; -- i) {
if(f[i][(1 << n) - 1] != - 1) {
cout << f[i][(1 << n) - 1] <<'\n';
break;
}
}
return 0;
}