题目大意:
就是给你
n
n
n个数和一个数字
d
d
d,问你从这n个数中挑出若干个数,使得这些数的乘积最后的一个数字是d,并且结果是最大的,问你要挑出哪些数字?
n
∈
[
1
,
1
e
5
]
,
a
i
∈
[
1
,
1000
]
n\in[1,1e5], a_i\in[1,1000]
n∈[1,1e5],ai∈[1,1000]
解题思路:
1.首先这种最大/最小值挑法并且要求乘积最大一看就有点像dp
2.那么我们就可以提出一种dp方程:dp[i][j]表示,前i个数中乘积结尾为j的乘出来的数最大是多少?
3.我们看一下这里有1e5个假设每个数都是最大那么乘积出来的数字最大可以达到
1
0
2
e
5
10^{2e5}
102e5这是非常大的数字那么我们该如何转移方程呢?
4.对于乘积过大我们可以取log,把乘积变成加法。
5.
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
−
1
]
[
k
]
+
x
)
[
x
=
l
o
g
a
[
i
]
&
&
k
∗
a
[
i
]
=
j
]
dp[i][j] = max(dp[i-1][j],dp[i-1][k]+x)[x=loga[i] \&\& k*a[i]=j]
dp[i][j]=max(dp[i−1][j],dp[i−1][k]+x)[x=loga[i]&&k∗a[i]=j]
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int maxn = 1e5 + 10;
int n, d, a[maxn];
double f[maxn][15];
PII pre[maxn][15];//用来记录dp转移过程的数组。
int num[maxn][15];
int idx, ans[maxn];
int main() {
cin >> n >> d;
for(int i = 0; i <= 9; ++ i) f[0][i] = -1e9, pre[0][i] = {-1,-1};
for(int i = 1; i <= n; ++ i) {
cin >> a[i];
double x = log2(a[i]);
for(int j = 0; j <= 9; ++ j) f[i][j] = f[i - 1][j], pre[i][j] = pre[i - 1][j], num[i][j] = num[i - 1][j];
for(int j = 0; j <= 9; ++ j) {
int k = j * a[i] % 10;
if(k == a[i] % 10) {
if(f[i][k] < (double)x)
pre[i][k] = {-1,i}, f[i][k] = x, num[i][k] = k;
}
if(f[i - 1][j] == -1e9) continue;
if(f[i - 1][j] + x > f[i][k]) {
f[i][k] = f[i - 1][j] + x;
pre[i][k] = {pre[i - 1][j].second,i};
num[i][k] = j;
}
}
}
if(f[n][d] == -1e9) {
cout << "-1";
return 0;
}
// for(int i = 1; i <= n; ++ i)
// for(int j = 0; j <= 9; ++ j)
// cout << "{" << pre[i][j].first << "," << pre[i][j].second << "}" << " \n"[j == 9];
// cout << endl;
// for(int i = 1; i <= n; ++ i)
// for(int j = 0; j <= 9; ++ j)
// cout << num[i][j] << " \n"[j == 9];
while(pre[n][d].first != -1) {
ans[idx ++] = a[pre[n][d].second];
// cout << pre[n][d].second <<endl;
int t = d;
d = num[n][d];
n = pre[n][t].first;
}
ans[idx++] = a[pre[n][d].second];
cout << idx << endl;
for(int i = 0; i < idx; ++ i)
cout << ans[i] << " ";
return 0;
}
/*
for(int i = 1; i <= n; ++ i) {
cin >> a[i];
//double x = log(a[i]);
int x = a[i];
for(int j = 0; j <= 9; ++ j) f[i][j] = f[i - 1][j];
for(int j = 0; j <= 9; ++ j) {
int k = j * a[i] % 10;
if(k == a[i] % 10)
f[i][k] = max(f[i][k],(double)a[i]);
if(f[i - 1][j] * x > f[i][k]) {
f[i][k] = f[i - 1][j] * x;
}
}
}
*/