题目链接:https://www.luogu.com.cn/problem/P1043
简单题意:将n个数(环形)分成k份,每份内求和对10取模,求各份相乘后的最大值和最小值
设f[i][j][l]表示将i到j分成l份的最大(小)值,则有f[i][j][l]=max(min)(f[i][j][l],f[i][t][l-1]*sum(t+1,j))。一个技巧就是把环复制一倍变成链,这个技巧在能量项链遇到过,poj1179好像也用到了(虽然还木有做),还是挺常见的技巧。注意把l=1的情况初始化,还有c++默认负数取模的问题,要用((x%mod)+mod)%mod将结果变成正数
#include<bits/stdc++.h> using namespace std; int n,i,j,k,l,m,t,ans1,ans2; int a[110],s[110],f1[110][110][15],f2[110][110][15]; int sum(int p,int q){ return ((s[q]-s[p-1])%10+10)%10;} int main(){ scanf("%d%d",&n,&k); for (i=1;i<=n;i++) scanf("%d",&a[i]); for (i=n+1;i<=2*n-1;i++) a[i]=a[i-n]; for (i=1;i<=2*n-1;i++) s[i]=s[i-1]+a[i]; for (m=0;m<=n;m++) for (i=1;i<=2*n-1;i++){ j=i+m; if (j<=2*n-1) f1[i][j][1]=f2[i][j][1]=sum(i,j); } for (l=2;l<=k;l++) for (m=1;m<=n;m++){ if (m<k-1) continue; for (i=1;i<=2*n-1;i++){ int j=i+m; if (j>2*n-1) continue; f1[i][j][l]=1e9;f2[i][j][l]=0; for (t=i;t<=j-1;t++) if (t-i+1>=l-1){ f1[i][j][l]=min(f1[i][j][l],f1[i][t][l-1]*sum(t+1,j)); f2[i][j][l]=max(f2[i][j][l],f2[i][t][l-1]*sum(t+1,j)); } } } ans1=1e9;ans2=0; for (i=1;i<=n;i++){ ans1=min(ans1,f1[i][i+n-1][k]); ans2=max(ans2,f2[i][i+n-1][k]); } printf("%d %d ",ans1,ans2); return 0; }