0%

D.小美的元素删除

D.小美的元素删除

题目描述:

小美有一个数组,她希望删除 $k$ 个元素,使得剩余的元素两两之间互为倍数关系。你能告诉小美有多少种删除方案吗?

由于答案过大,请对 $10^9 + 7$ 取模。

数据范围:

$1\le k \le n \le 10^3;1\le a_i \le 10^9$

题解:

首先肯定是需要排序,然后使用动态规划计数。但是好像定义 $dp[i][j]$ 为从前 $i$ 个中删除 $j$ 个,并且末尾是 $nums[i]$ 不好计算。

考虑反面,从数组中选出 $n - k$ 个元素,有多少种选法。定义 $dp[i][j]$ 表示以 $nums[i]$ 为最后一个元素,选出了 $j$ 个的方案数。那么可以得到

如果以 $nums[i]$ 结尾,那么需要往前找到 $nums[p]$ ,这时从前 $i$ 个中选出 $j$ 个就转化为了从前 $p$ 个中选出 $j-1$ 再加上 $nums[i]$ 。

最后需要统计以每一个元素结尾时取 $n - k$ 个元素的总方案和。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// #pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define lll long long
#define PII pair<int, int>
namespace FAST_IO
{

inline char nextChar()
{
static char buf[1000000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}
#define getch getchar
template <class T>
inline void read(T &x)
{
T flag = 1;
x = 0;
char ch = getch();
while (ch < '0' || ch > '9')
{
if (ch == '-')
flag = -1;
ch = getch();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 3) + (x << 1) + (ch ^ 48), ch = getch();
}
x *= flag;
}

template <class T, class... _T>
inline void read(T &x, _T &...y)
{
return read(x), read(y...);
}

inline void print128(lll x)
{
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
print128(x / 10);
putchar(x % 10 + '0');
}

} // namespace FAST_IO
using namespace std;
using namespace FAST_IO;
const ll mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const ll INF_LL = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-5;
const int maxn = 1e3 + 10;
const int maxm = 1e5 + 10;
int t, n, m, k;
int a[maxn];
ll dp[maxn][maxn];
int main()
{
// #define COMP_DATA
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int tcase;
read(n, k);
k = n - k;
for (int i = 1; i <= n; ++i)
{
read(a[i]);
}
sort(a + 1, a + n + 1);
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; ++i)
{
dp[i][1] = 1;
}
for (int i = 2; i <= n; ++i)
{
for (int p = 1; p < i; ++p)
{
if (a[i] % a[p])
continue;
for (int j = 2; j <= min(k, i); ++j)
{
dp[i][j] = (dp[i][j] + dp[p][j - 1]) % mod;
}
}
}
ll ans = 0;
for (int i = 1; i <= n; ++i)
{
ans = (ans + dp[i][k]) % mod;
}
cout << ans << endl;
return 0;
}