vijos p1347&&vijos p1455(递推)

来源:互联网 发布:淘宝退款几天到银行卡 编辑:程序博客网 时间:2024/06/06 01:19

1.vijos1347

链接:点击打开链接

题意:有一个长度N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大

代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;char s[55];long long sum[55][55],dp[55][10];int main(){                                     //dp[i][j]表示到第i位,分成j段的最大值    long long n,k,i,j,p;    while(scanf("%I64d%I64d",&n,&k)!=EOF){        scanf("%s",s+1);        for(i=1;i<=n;i++){            sum[i][i]=s[i]-'0';            for(j=i+1;j<=n;j++)            sum[i][j]=sum[i][j-1]*10+s[j]-'0';        }        k++;        memset(dp,0,sizeof(dp));        for(i=1;i<n;i++)        dp[i][1]=sum[1][i];        for(i=1;i<=n;i++){                      //根据段数进行转移            for(j=2;j<=min(i,k);j++){                for(p=max(1ll,j-1);p<=i-1;p++){                    dp[i][j]=max(dp[i][j],dp[p][j-1]*sum[p+1][i]);                }            }        }        printf("%I64d\n",dp[n][k]);    }    return 0;}

2.vijos1455

链接:点击打开链接

题意:已知一个数串,可以在适当的位置加入乘号(设加了k个,当然也可不加,即分成k+1个部分),设这k+1个部分的乘积(如果k=0,则乘积即为原数串的值)对m 的余数(即mod m)为x;现求x能达到的最小值及该情况下k的最小值,以及x能达到的最大值及该情况下的k的最小值(可以存在x的最小值与最大值相同的情况)

代码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const long long INF=0x3f3f3f3f3f3f3f3f;char s[1005];long long dp[1005][105],sum[1005][1005];int main(){                                     //dp[i][j]表示到第i位,余数是j最小添加的乘号数    long long i,j,k,n,m,ans1,ans2,sum1,sum2;    while(scanf("%s%I64d",s+1,&m)!=EOF){        n=strlen(s+1);        for(i=1;i<=n;i++){            sum[i][i]=(s[i]-'0')%m;            for(j=i+1;j<=n;j++)            sum[i][j]=(sum[i][j-1]*10+s[j]-'0')%m;        }                                       //和上一道题一样预处理出所有区间        memset(dp,INF,sizeof(dp));        for(i=1;i<=n;i++){            dp[i][sum[1][i]]=0;            for(j=1;j<i;j++){                   //根据余数进行转移                for(k=0;k<m;k++){                    if(dp[j][k]!=INF)                    dp[i][k*sum[j+1][i]%m]=min(dp[i][k*sum[j+1][i]%m],dp[j][k]+1);                }            }        }        for(i=0;i<m;i++){                       //找最大值和最小值            if(dp[n][i]!=INF){                sum1=i;                ans1=dp[n][i];                break;            }        }        for(i=m-1;i>=0;i--){            if(dp[n][i]!=INF){                sum2=i;                ans2=dp[n][i];                break;            }        }        printf("%I64d %I64d %I64d %I64d\n",sum1,ans1,sum2,ans2);    }    return 0;}

0 0
原创粉丝点击