一个长度为n的数组a,我们可以把它分成任意组,每一组是一段连续的区间。
比如数组1,2,3,4,5可以分成(1,2),(3,4,5)两个组。每个分组都有一个权值,这个权值就是分组里面每个数的乘积对1000取模的结果。对于数组a的一个分组方案,总权值就是每个分组的权值和。
那么对于数组a,分组以后最大的权值和是多少?
输入格式
输入第一行一个整数n(1≤n≤1000)。
接下来一行n个整数,表示数组a,数组中每个元素都小于等于100。
输出格式
数组最大的分组权值和。
样例输入
7 52 26 1 36 72 48 43
样例输出
1596
我们用dp[i]表示前i个数分组的最大权值,对于位置i,我们可以枚举最后一个分组的起始位置为j,计算i,j之间的权值,然后更新dp[i]即可。
为了避免过多的计算,我们需要预处理出来每个区间的乘积对1000取模的结果。
1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <sstream> 13 const int INF=0x3f3f3f3f; 14 typedef long long LL; 15 const int mod=1e9+7; 16 const double PI = acos(-1); 17 const double eps =1e-8; 18 #define Bug cout<<"---------------------"<<endl 19 const int maxn=1e5+10; 20 using namespace std; 21 22 int a[1010]; 23 int sum[1010][1010];//sum[i][j]表示区间i~j的乘积对1000的模 24 int dp[1010]; 25 26 int main() 27 { 28 int n; 29 scanf("%d",&n); 30 for(int i=1;i<=n;i++) 31 scanf("%d",&a[i]); 32 for(int i=1;i<=n;i++)//预处理 33 { 34 sum[i][i]=a[i]; 35 for(int j=i+1;j<=n;j++) 36 sum[i][j]=sum[i][j-1]*a[j]%1000; 37 } 38 dp[1]=a[1]; 39 for(int i=2;i<=n;i++)//求dp[i] 40 { 41 for(int j=1;j<i;j++)//向前遍历j,更新dp[i] 42 dp[i]=max(dp[i],dp[j]+sum[j+1][i]); 43 } 44 printf("%d ",dp[n]); 45 return 0; 46 }
-