传送门
思路:
设 f[ i ][ j ] 为第 i 节,切到第 j 段的最大恶心值。
枚举 左端点 j ,右端点 i ,段数 k → 转移: f [ i ][ k ] = max ( f [ i ][ k ],f [ j ][ k -1 ] + sum [ j ~i ])。( sum [ j~i ] 为 j~i 段的异或和 )
昨天就是因为异或前缀和 “出锅” ,只要改成每次枚举暴力地求出区间( i,j) 的异或和就 A 了。
Code:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<string> #include<algorithm> #include<iostream> #include<set> #include<map> #include<stack> #include<vector> #include<queue> #include<deque> using namespace std; #define INF 0x3f typedef long long LL; const int maxn=1e3+7; LL n,m,las,a[maxn],f[maxn][105]; inline LL read() { LL kr=1,xs=0;char ls; ls=getchar(); while(!isdigit(ls)) { if(!(ls^45)) kr=-1; ls=getchar(); } while(isdigit(ls)) { xs=(xs<<1)+(xs<<3)+(ls^48); ls=getchar(); } return xs*kr; } inline void clear() { memset(f,-INF,sizeof(f)); f[0][0]=0; } int main() { n=read();m=read();clear(); for(LL i=1;i<=n;i++) a[i]=read(); for(LL i=1;i<=n;i++) { las=a[i]; for(LL j=i-1;~j;j--) { for(LL k=1;k<=m;k++) f[i][k]=max(f[i][k],f[j][k-1]+las); las^=a[j]; } } printf("%lld ",f[n][m]); return 0; }