题目链接:
题目大意:
给你n本书以及每本书的价值,现在让你把n本书放到k个书架上(只有连续的几本书可以放到一个书架上),每个书架的价值值是书架上每本书的价值和,总的价值每个书架权值按位与的结果,要求输出最大的总价值。解题思路:按位从高到低枚举,每次都判断一下是否符合条件(即判断ans|(1<<i)是否能够取到),如果符合则更新答案。判断过程:设dp[i][j]表示将1~i分为j段是否符合条件,然后枚举区间,状态转移方程为dp[i][j]|=dp[i-1][k-1],( ((a[j]-a[i])&ans)==ans,0<=i<j<=n )最后只要判断dp[n][k]是否为1即可。
代码:
1 #include2 #define lc(a) (a<<1) 3 #define rc(a) (a<<1|1) 4 #define MID(a,b) ((a+b)>>1) 5 #define fin(name) freopen(name,"r",stdin) 6 #define fout(name) freopen(name,"w",stdout) 7 #define clr(arr,val) memset(arr,val,sizeof(arr)) 8 #define _for(i,start,end) for(int i=start;i<=end;i++) 9 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);10 using namespace std;11 typedef long long LL;12 const int N=1e2+5;13 const int INF=0x3f3f3f3f;14 const double eps=1e-10;15 16 int n,p;17 LL a[N],dp[N][N];//dp[i][j]表示1~i分j段是否符合条件 18 19 bool check(LL x){20 memset(dp,0,sizeof(dp));21 dp[0][0]=1;22 for(int k=1;k<=p;k++){23 for(int i=0;i >n>>p;38 for(int i=1;i<=n;i++){39 cin>>a[i];40 a[i]+=a[i-1];41 }42 LL ans=0;43 for(int i=60;i>=0;i--){44 ans|=(1LL<