習題:Round Subset(揹包)
阿新 • • 發佈:2020-08-24
題目
思路
考慮如果末尾是0,那麼一定是一個2和一個5組合起來
之後就是揹包的板子了
這裡有一個小優化,第二位考慮5的數量而不是2的數量
程式碼
#include<iostream> #include<cstring> using namespace std; int dp[2][205][5155];//滾動,選了j個數,有k個5,最大能選出的2 int n,m,ans; int cnt2[205],cnt5[205],limit; int la,now; void divide(long long val,int _ind) { if(val==0) return; while(val%2==0) { cnt2[_ind]++; val/=2; } while(val%5==0) { cnt5[_ind]++; val/=5; } limit+=cnt5[_ind]; } int main() { cin>>n>>m; for(int i=1;i<=n;i++) { long long val; cin>>val; divide(val,i); } //for(int i=1;i<=n;i++) // cout<<cnt2[i]<<' '<<cnt5[i]<<endl; memset(dp,-1,sizeof(dp)); la=0,now=1; dp[1][0][0]=0; dp[0][0][0]=0; for(int i=1;i<=n;i++) { la=now; now^=1; for(int j=1;j<=min(i,m);j++) { for(int k=0;k<=limit;k++) { dp[now][j][k]=dp[la][j][k]; if(k<cnt5[i]) continue; if(dp[la][j-1][k-cnt5[i]]!=-1) { dp[now][j][k]=max(dp[la][j][k],dp[la][j-1][k-cnt5[i]]+cnt2[i]); if(j==m) ans=max(ans,min(dp[now][j][k],k)); } } } } cout<<ans; return 0; } /* 3 1 1000000000000000000 800000000000000000 625 */