洛谷 P1018 乘積最大(動態規劃 高精度)

2021-08-26 05:50:27 字數 2550 閱讀 5807

題目鏈結

今年是國際數學聯盟確定的「2000――世界數學年」,又恰逢我國著名數學家華羅庚先生誕辰90周年。在華羅庚先生的家鄉江蘇金壇,組織了一場別開生面的數學智力競賽的活動,你的乙個好朋友xz也有幸得以參加。活動中,主持人給所有參加活動的選手出了這樣一道題目:

設有乙個長度為n的數字串,要求選手使用k個乘號將它分成k+1個部分,找出一種分法,使得這k+1個部分的乘積能夠為最大。

同時,為了幫助選手能夠正確理解題意,主持人還舉了如下的乙個例子:

有乙個數字串:312, 當n=3,k=1時會有以下兩種分法:

1、3×12=36 2、31×2=62

這時,符合題目要求的結果是: 31×2=62

現在,請你幫助你的好朋友xz設計乙個程式,求得正確的答案。

輸入格式:

程式的輸入共有兩行:

第一行共有2個自然數n,k(6≤n≤40,1≤k≤6)

第二行是乙個長度為n的數字串。

輸出格式:

結果顯示在螢幕上,相對於輸入,應輸出所求得的最大乘積(乙個自然數)。

輸入樣例#1:複製

4  2

1231

輸出樣例#1:複製

62
預處理中可以先把字串中第i至j位的數都算出來,用num[i][j]表示。

用dp[i][j]表示前i個數插入j個乘號所得的最大乘積,遞推關係時,dp[i[[j]與dp[k][j-1]有關聯,其中k的範圍是[j,i-1],表示最後乙個乘號的位置(第k個數與第k+1個數的間隔)。

80分**:

#include#include#include#include#include#include#include#include#includeusing namespace std;

__int128 dp[42][7];//dp[i][j]表示前i個數插入j個乘號的最大乘積 (從1開始)

__int128 num[42][42];//num[i][j]表示字串中第i位至第j為組成的數(從1開始)

inline void output(__int128 a)

int main()

for(int i=1;i<=n;i++) dp[i][0]=num[1][i];

for(int j=1;j<=k;j++)//乘號個數

for(int i=2;i<=n;i++)//前i個數

for(int k=j;k<=i-1;k++)//最後乙個乘號放在第k個數後第k+1個數前

dp[i][j]=max(dp[i][j],dp[k][j-1]*num[k+1][i]);

output(dp[n][k]);

}

ac**:

#include#include#include#include#include#include#include#include#includeusing namespace std;

struct wint:vector//用標準庫vector做基類,完美解決位數問題,同時更易於實現

wint& check()//在各類運算中經常用到的進製小函式,不妨內建

return *this;//為使用方便,將進製後的自身返回引用

}};//輸入輸出

istream& operator>>(istream &is,wint &n)

ostream& operator<<(ostream &os,const wint &n)

bool operator==(const wint &a,const wint &b)

bool operator<(const wint &a,const wint &b)

bool operator>=(const wint &a,const wint &b)

}return a.check();

}wint operator-(wint a,const wint &b)

//乘法不能先實現*=,原因自己想

wint operator*(const wint &a,const wint &b)

wint& operator*=(wint &a,const wint &b)

wint dp[42][7];//dp[i][j]表示前i個數插入j個乘號的最大乘積 (從1開始)

wint num[42][42];//num[i][j]表示字串中第i位至第j為組成的數(從1開始)

int main()

for(int i=1;i<=n;i++) dp[i][0]=num[1][i];

for(int j=1;j<=k;j++)//乘號個數

for(int i=2;i<=n;i++)//前i個數

for(int k=j;k<=i-1;k++)//最後乙個乘號放在第k個數後第k+1個數前

dp[i][j]=max(dp[i][j],dp[k][j-1]*num[k+1][i]);

cout<}

洛谷 P1018 乘積最大

題目描述 今年是國際數學聯盟確定的 2000 世界數學年 又恰逢我國著名數學家華羅庚先生誕辰90周年。在華羅庚先生的家鄉江蘇金壇,組織了一場別開生面的數學智力競賽的活動,你的乙個好朋友xz也有幸得以參加。活動中,主持人給所有參加活動的選手出了這樣一道題目 設有乙個長度為n的數字串,要求選手使用k個乘...

洛谷P1018 乘積最大

洛谷p1018 乘積最大 題意 給乙個長度為n的數字串,在這個數字串中插入k個乘號,使得表示式的乘積最大 分析一下 算了,懶得分析了,中有詳細注釋,直接看 吧 君 include using namespace std const int maxn 45 struct biginteger bigi...

洛谷 P1018 乘積最大

今年是國際數學聯盟確定的 20002000 世界數學年 又恰逢我國著名數學家華羅庚先生誕辰 9090 周年。在華羅庚先生的家鄉江蘇金壇,組織了一場別開生面的數學智力競賽的活動,你的乙個好朋友 xzxz 也有幸得以參加。活動中,主持人給所有參加活動的選手出了這樣一道題目 設有乙個長度為 nn 的數字串...