丁丁最近沉迷於乙個數字遊戲之中。這個遊戲看似簡單,但丁丁在研究了許多天之後卻發覺原來在簡單的規則下想要贏得這個遊戲並不那麼容易。遊戲是這樣的,在你面前有一圈整數(一共n個),你要按順序將其分為m個部分,各部分內的數字相加,相加所得的m個結果對10取模後再相乘,最終得到乙個數k。遊戲的要求是使你所得的k最大或者最小。
例如,對於下面這圈數字(n=4,m=2):
要求最小值時,((2-1) mod 10)×((4+3) mod 10)=1×7=7,要求最大值時,為((2+4+3) mod 10)×(-1 mod 10)=9×9=81。特別值得注意的是,無論是負數還是正數,對10取模的結果均為非負值。
丁丁請你編寫程式幫他贏得這個遊戲。
輸入格式:
輸入檔案第一行有兩個整數,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有個整數,其絕對值不大於104,按順序給出圈中的數字,首尾相接。
輸出格式:
輸出檔案有兩行,各包含乙個非負整數。第一行是你程式得到的最小值,第二行是最大值。
輸入樣例#1:
4 243輸出樣例#1:-12
7思路一:81
狀態:把環拆成鏈,列舉開始位置(o(n)^4)
d[i][j]表示前i個數分成j部分的最優值
狀態轉移方程:
d[i][j]=opt(d[i][j],d[k][j-1]*(((s[i]-s[k])%10+10)%10))
s[i]是前i個數的和
邊界:d[0][0]=1;
d[i][1]=((s[i]%10+10)%10)
思路二:
把環看成兩倍的線性長 (o(n)^3)
思路三:
%n 對n取模 (o(n)^3)
這種的話狀態轉移方程f[i][j],i表示起點,j表示長度
1 #include2 #include3using
namespace
std;45
int n,m,max,min,s[55],d[55][10],dp[55][10];6
void dp(inta)7
17 d[0][0]=dp[0][0]=1;18
for(i=1;i<=n;i++)
19 d[i][1]=dp[i][1]=(s[i]%10+10)%10;20
for(j=2;j<=m;j++)
21for(i=j;i<=n;i++)
22for(k=j-1;k)
23
27 max=max(max,d[n][m]);
28 min=min(min,dp[n][m]);29}
30int
main()
3142
for(j=0;j)
43 dp(a+j);
44 printf("
%d\n%d\n
",min,max); 45}
46 }
P1043 數字遊戲
給乙個由 n nn 個數組成的環,講環拆成 m mm 份,每份求和最後相乘,求最大 最小值。一道區間 dpdp dp題,首先因為是環,常規做法就是拆環,用兩倍數組裝,又要對每份求和,那就需要用到字首和。陣列 dp i j dp i j dp i j 表示將 j jj 個數分成 i ii 份的最大 最...
P1043 數字遊戲
丁丁最近沉迷於乙個數字遊戲之中。這個遊戲看似簡單,但丁丁在研究了許多天之後卻發覺原來在簡單的規則下想要贏得這個遊戲並不那麼容易。遊戲是這樣的,在你面前有一圈整數 一共n個 你要按順序將其分為m個部分,各部分內的數字相加,相加所得的m個結果對10取模後再相乘,最終得到乙個數k。遊戲的要求是使你所得的k...
P1043 數字遊戲
研究環狀dp 可以開雙倍大小的陣列用以表示環 表示為 f i j l 從i 到 l 的區間裡,劃分 l 段 進行遞推前,需要初始化 f i j 1 然後有乙個小細節就是sum 進行字首和優化 將 o n 的東西優化成 o 1 可以加快節奏 讀取最值時記得掃一遍環 f i i n 1 i 1 n 狀態...