题意:
解法:
一个显然的想法是令d[i][j]表示前i个数,末位为j的最大乘积,dp转移的时候记录路径即可.
但是这题数没办法直接相乘,会爆longlong.
考虑到只需要比较大小,而且还是比较乘积的大小,因此可以使用对数:
如果a>b,那么log(a)>log(b),且log(a*b)=log(a)+log(b),转换成了加法.
那么我们只需要记录最大的和就行了,因此:
令d[i][j]表示前i个数,末位为j的最大乘积的log值,dp转移的时候记录路径即可.
code:
#include<bits/stdc++.h>
#define int long long
#define PI pair<int,int>
using namespace std;
const int maxm=1e5+5;
PI pre[maxm][10];
double d[maxm][10];
int a[maxm];
double v[maxm];
int n,dig;
int cal(int x,int y){
x%=10,y%=10;
return (x*y)%10;
}
void solve(){
cin>>n>>dig;
for(int i=1;i<=n;i++){
cin>>a[i];
v[i]=log(a[i]);
}
for(int i=0;i<=n;i++){
for(int j=0;j<10;j++){
d[i][j]=-1e9;
}
}
d[0][1]=0;
for(int i=0;i<n;i++){
for(int j=0;j<10;j++){
if(d[i][j]<0)continue;
if(d[i][j]>d[i+1][j]){
d[i+1][j]=d[i][j];
pre[i+1][j]={j,0};
}
int nt=cal(j,a[i+1]);
double val=d[i][j]+v[i+1];
if(val>d[i+1][nt]){
d[i+1][nt]=val;
pre[i+1][nt]={j,1};
}
}
}
if(d[n][dig]<=0){
cout<<-1<<endl;
}else{
vector<int>ans;
int x=dig;
for(int i=n;i>=1;i--){
PI pre1=pre[i][x];
x=pre1.first;
if(pre1.second)ans.push_back(a[i]);
}
reverse(ans.begin(),ans.end());
cout<<ans.size()<<endl;
for(auto i:ans){
cout<<i<<' ';
}
cout<<endl;
}
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);
solve();
return 0;
}