1 条题解
-
2
二进制最优化的题,很容易想到从高位向低位考虑。我们枚举当前位,判断其能否为。
我们记录一个当前答案。设正在考虑从高到低第位。
很容易想到表示考虑了前个数,能否在满足前位与的或等于的情况下分成段。转移时枚举上一段的结尾即可。这个可以优化到。好像有人这样过去了。
我们发现满足,这显然是有说法的。我们对数据点分类讨论,这里设表示考虑了前个数,在满足前位与的或等于的情况下能分成的最小段数。
然后做就行了。总复杂度。
数据怎么这么水,全当做有#include<bits/stdc++.h> using namespace std; #define int long long #define lb(x) x&(-x) #define ls(p) (p<<1) #define rs(p) ((p<<1)|1) #define pii pair<int,int> #define F first #define S second #define mkp make_pair const int mod=998244353,inf=1e15; int n,A,B,a[101000],sum[101000]; int dp[2020]; bitset<110>dp1[110]; signed main(){ // freopen("data.in","r",stdin); // freopen("my.out","w",stdout); // system("fc my.out ex.out");return 0; ios::sync_with_stdio(0); cin.tie(0); cin>>n>>A>>B; for(int i=1;i<=n;i++) cin>>a[i],sum[i]=sum[i-1]+a[i]; if(n<=100){ int ans=0; for(int idw=45;idw>=0;idw--){ for(int i=1;i<=n;i++) dp1[i].reset(); dp1[0][0]=1; for(int i=1;i<=n;i++){ for(int fr=0;fr<i;fr++){ int val=(((sum[i]-sum[fr])>>idw)<<idw); if((val|ans)!=ans) continue; dp1[i]=(dp1[i]|(dp1[fr]<<1)); } } int flag=0; for(int i=A;i<=B;i++){ if(dp1[n][i]){ flag=1; break; } } if(flag==0) ans=ans+(1ll<<idw); }cout<<ans; }else{ int ans=0; for(int idw=45;idw>=0;idw--){ for(int i=1;i<=n;i++) dp[i]=inf; dp[0]=0; for(int i=1;i<=n;i++){ for(int fr=0;fr<i;fr++){ int val=(((sum[i]-sum[fr])>>idw)<<idw); if((val|ans)!=ans) continue; dp[i]=min(dp[i],dp[fr]+1); } } if(dp[n]>B) ans=ans+(1ll<<idw); }cout<<ans; } return 0; }
信息
- ID
- 780
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- (无)
- 递交数
- 35
- 已通过
- 7
- 上传者