https://www.luogu.com.cn/problemnew/solution/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
状态转移方程为 f [ i ] [ j ] [ l ] = min或max( f [ i ] [ j ] [ l ] , f [ i ] [ k ] [ l-1 ] * f [ k-1 ] [ j ] [ 1 ] ) (i <= k < j )
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define py 1e8 5 #define ll long long 6 using namespace std; 7 8 inline ll judging(ll a) 9 { 10 return ((a%10)+10)%10; 11 } 12 13 ll sum[10000]; 14 ll f[105][105][100]; 15 ll f0[105][105][100]; 16 17 int main() 18 { 19 memset(f0,0x7f,sizeof(f0)); 20 int n,m; 21 ios_base::sync_with_stdio(false); 22 cout.tie(NULL); 23 cin>>n>>m; 24 for(int i=1;i<=n;i++) 25 { 26 cin>>sum[i]; 27 sum[i+n]=sum[i]; 28 } 29 for(int i=1;i<= n * 2; i++) 30 { 31 sum[i]+=sum[i-1];//cout<<sum[] 32 } 33 34 for(int i=1;i<=2 * n;i++) 35 for(int j=i;j<=2 * n;j++) 36 { 37 f[i][j][1]=judging(sum[j] - sum[i-1]); 38 f0[i][j][1]=judging(sum[j] - sum[i-1]); 39 } 40 for(int l=2;l<=m;l++) 41 for(int i=1;i<=2 * n;i++) 42 for(int j=i+l-1;j<=2 * n;j++) 43 { 44 for(int k=i+l-2;k<j;k++) 45 { 46 f[i][j][l]=max(f[i][j][l],f[i][k][l-1] * f[k+1][j][1]); 47 f0[i][j][l]=min(f0[i][j][l],f0[i][k][l-1] * f0[k+1][j][1]); 48 } 49 } 50 ll maxn=0,minn=0x7f; 51 52 for(int i=1;i<=n;i++) 53 { 54 maxn=max(maxn,f[i][i+n-1][m]); 55 minn=min(minn,f0[i][i+n-1][m]); 56 } 57 cout<<minn<<' '<<maxn; 58 }
嗯……
有一个很讨厌的的地方
就是不要以为 2 * n 最大是50,就开 f[100] [100] [10]
我就是这样,少开了一位!就一位!)
喜提RE
-end-