Educational Codeforces Round 26-D. Round Subset
Posted notnight
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 26-D. Round Subset相关的知识,希望对你有一定的参考价值。
题目大意:给你n个数字(小于1e18),从n个数中取k个数字相乘,使其后缀0最多,问你后缀0最多是多少。
知道得用三维的dp[ i ] [ j ] [ k ] 第一维表示用到第 i 个数为止,j 表示从中选 j 个数,想了好久也不知道
第三维是什么,我想不到怎么总结当前状况相乘之后 0 的个数QAQ。
思路:其实后面0的个数就是相乘之后有多少个10,10可以分解成 2 * 5,这样我们只要统计每个数字中
有多少个2的因子和5的因子就好了。dp [ i ][ j ][ k ]表示,在(1 - i )之间取 j 个数,5因子的数量为 k 的
情况,2的因子的最大个数。c1[ i ] 表示第 i 个数的因子中有多少个 2 ,c2[ i ]表示有多少个5
状态转移方程 dp[ i ][ j ][ k ]=max(dp[ i ][ j ][ k ] , dp[ i -1 ][ j - 1][ k-c2[ i ] ] + c1[ i ]); dp[ i ][ j ][ k ]=max( dp[ i ][ j ][ k ] , dp[ i - 1 ][ j ][ k ] )。
还需要注意一点要用滚动数组,不然会MLE。
#include<bits/stdc++.h> #define ll long long using namespace std; const int inf=0x3f3f3f3f; int n,k,c1[205],c2[205],dp[2][205][5001]; ll a[205]; void work(ll x,int id) { ll y=x; int cnt=0; while(!(y&1)) { cnt++; y>>=1; } c1[id]=cnt; cnt=0; while(x%5==0) { cnt++; x/=5; } c2[id]=cnt; } int main() { cin>>n>>k; memset(dp,-1,sizeof(dp)); for(int i=1;i<=n;i++) { scanf("%I64d",&a[i]); work(a[i],i); } for(int i=0;i<=1;i++)for(int j=0;j<k;j++)for(int u=0;u<=5000;u++) dp[i&1][j][u]=-inf; dp[0][0][0]=0; for(int i=1;i<=n;i++) { for(int u=0;u<=k;u++) { for(int j=0;j<=5000;j++) dp[i&1][u][j]=-inf; } for(int u=0;u<=k;u++) { for(int j=0;j<=5000;j++) { if(j-c2[i]>=0 && u-1>=0) dp[i&1][u][j]=max(dp[i&1][u][j],c1[i]+dp[(i+1)&1][u-1][j-c2[i]]); dp[i&1][u][j]=max(dp[i&1][u][j],dp[(i+1)&1][u][j]); } } } int mx=0; for(int i=0;i<=5000;i++) mx=max(mx,min(i,dp[n&1][k][i])); cout<<mx<<endl; return 0; }
以上是关于Educational Codeforces Round 26-D. Round Subset的主要内容,如果未能解决你的问题,请参考以下文章
Educational Codeforces Round 7 A
Educational Codeforces Round 7
Educational Codeforces Round 90
Educational Codeforces Round 33