非常好的二进制dp题
参考了这位大佬的思路:https://www.cnblogs.com/zbtrs/p/8495170.html
#include<iostream> #include<cstdio> #include<algorithm> #include<string> #include<cstring> #include<cmath> #include<queue> using namespace std; typedef long long ll; const ll N=2e3+10,inf=1e18; ll n,A,B,len,ans,s[N],f[N][N],g[N]; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } inline void solve1(){ while(len){ for(ll i=1;i<=n;i++) for(ll j=1;j<=min(i,B);j++) f[i][j]=0; f[0][0]=1; for(ll i=1;i<=n;i++){ for(ll j=1;j<=min(i,B);j++){ for(int k=0;k<i;k++){ if(f[k][j-1]){ ll t=s[i]-s[k]; if((!(t&(1ll<<(len-1))))&&((ans|(t>>len))==ans)) f[i][j]=1; } } } } int flag=0; for(int i=A;i<=B;i++) if(f[n][i]){flag=1;break;} if(flag) ans=ans<<1; else ans=ans<<1|1; len--; } } inline void solve2(){ while(len){ for(int i=1;i<=n;i++) g[i]=inf; for(int i=1;i<=n;i++){ for(int j=0;j<i;j++){ ll t=s[i]-s[j]; if((!(t&(1ll<<(len-1))))&&((ans|(t>>len))==ans)) g[i]=min(g[i],g[j]+1); } } if(g[n]>B) ans=ans<<1|1; else ans=ans<<1; len--; } } int main(){ n=read();A=read();B=read(); for(int i=1;i<=n;i++) s[i]=s[i-1]+read(); ll t=s[n];len=0; while(t){len++;t>>=1;} if(A!=1) solve1(); else solve2(); return printf("%lld ",ans),0; }