很容易想到直接DP,关键是枚举顺序。
\(1.\)设后一段构成最后一个点,前一段构成前面的点,那么能得到\(1\)个点的数量要求 : \(1,k,2k-1...\)相差\(k-1\),所以能够剩下的位数是在模\(K-1\)意义下的\(2.\)因为实质是从里面转移到外面,注意循环的正逆顺序 : \(mid\)比\(j\)小 , 正序枚举\(j\) ; \(mid\)比\(i\)大 , 倒序枚举\(i\)具体细节见代码
#include#include #include #include #define debug(...) fprintf(stderr,__VA_ARGS__)#define Debug(x) cout<<#x<<"="< < 57){if(c=='-')f=-1;c=getchar();} while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar(); return f*x;}int f[305][305][305],g[2],c[305],w[305],a[305];int n,K,ans=-INF;signed main(){ n=read(),K=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=0;i<(1< =1;i--) for(int j=i;j<=n;j++){ //注意循环的正逆顺序:mid比j小,正序枚举j;mid比i大,倒序枚举i if(i==j){f[i][j][a[i]]=0;continue;} int len=j-i;//前一段得到的长度 len%=K-1; if(!len) len=K-1; for(int mid=j;mid>i;mid-=K-1)//能够得到1位的位数相差K-1 for(int op=0;op<(1<