【LOJ】#2886. 「APIO2015」巴厘岛的雕塑 Bali Sculptures

题解

感觉自己通过刷水题混LOJ刷题量非常成功

首先是二进制枚举位,判是否合法
要写两个solve不是很开心,(A)不为1的直接记录状态(f[i][j])为能否到达前(i)个分成(j)段,转移(n^3)

(A)为1的相当于在一张拓扑图上求到(N)的最短路是否小与(B),连边方式即为如果(sum[j] - sum[k])是二分值的一个子集则(k)(j)有边

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('
')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 505
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
	if(c == '-') f = -1;
	c = getchar();
    }
    while(c >= '0' && c <= '9') {
	res = res * 10 + c - '0';
	c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
	out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,A,B,l;
int64 y[2005],sum[2005];
int dp[2005];
bool f[105][105];
void Solve1() {
    int64 ans = 0;
    for(int i = l ; i >= 0 ; --i) {
	int64 t = ans + (1LL << i) - 1;
	
	for(int j = 1 ; j <= N ; ++j) {
	    dp[j] = N + 1;
	    for(int k = 0 ; k < j ; ++k) {
		if(((sum[j] - sum[k]) & t) == (sum[j] - sum[k])) dp[j] = min(dp[j],dp[k] + 1);
	    }
	}
	if(dp[N] > B) {ans |= (1LL << i);}
    }
    out(ans);enter;
}
void Solve2() {
    int64 ans = 0;
    for(int i = l ; i >= 0 ; --i) {
	int64 t = ans + (1LL << i) - 1;
	memset(f,0,sizeof(f));
	f[0][0] = 1;
	for(int j = 1 ; j <= N ; ++j) {
	    for(int k = 0 ; k < j ; ++k) {
		if(((sum[j] - sum[k]) & t) == (sum[j] - sum[k])) {
		    for(int h = 1 ; h <= j ; ++h) {
			f[j][h] |= f[k][h - 1];
		    }
		}
	    }
	}
	bool flag = 0;
	for(int k = A ; k <= B ; ++k) {
	    if(f[N][k]) {flag = 1;break;}
	}
	if(!flag) ans |= (1LL << i);
    }
    out(ans);enter;
}
void Init() {
    read(N);read(A);read(B);
    for(int i = 1 ; i <= N ; ++i) {read(y[i]);sum[i] = sum[i - 1] + y[i];}
    int64 t = sum[N];
    l = 0;
    while(t) {++l;t >>= 1;}
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    if(A == 1) Solve1();
    else Solve2();
}
原文地址:https://www.cnblogs.com/ivorysi/p/10139235.html