uoj #110. 【APIO2015】Bali Sculptures #110. 【APIO2015】Bali Sculptures
印尼巴厘岛的公路上有许多的雕塑,我们来关注它的一条主干道。
在这条主干道上一共有 Yi 年。为了使这条路的环境更加优美,政府想把这些雕塑分成若干组,并通过在组与组之间种上一些树,来吸引更多的游客来巴厘岛。
下面是将雕塑分组的规则:
- 这些雕塑必须被分为恰好 A≤X≤B,每组必须含有至少一个雕塑,每个雕塑也必须属于且只属于一个组。同一组中的所有雕塑必须位于这条路的连续一段上。
- 当雕塑被分好组后,对于每个组,我们首先计算出该组所有雕塑的年龄和。
- 计算所有年龄和按位取或的结果。我们这个值把称为这一分组的最终优美度。
请问政府能得到的最小的最终优美度是多少?
备注:将两个非负数 Q 按位取或是这样进行计算的:
- 首先把 Q 转换成二进制。
- 设 0 位是数的最低位。
-
(pM−1ORqM−1)(pM−2ORqM−2)…(p1ORq1)(p0ORq0)。其中:
- 0OR0=0
- 0OR1=1
- 1OR0=1
- 1OR1=1
输入格式
输入的第一行包含三个用空格分开的整数 N,A,B。
第二行包含 Y1,Y2,…,YN。
输出格式
输出一行一个数,表示最小的最终优美度。
样例一
input
6 1 3 8 1 2 1 5 4
output
11
explanation
将这些雕塑分为 (11OR10)=11。(不难验证,这也是最终优美度的最小值。)
子任务
- 子任务 1 (9 分)
- 1≤N≤20
- 1≤A≤B≤N
- 0≤Yi≤1000000000
- 子任务 2 (16 分)
- 1≤N≤50
- 1≤A≤B≤min{20,N}
- 0≤Yi≤10
- 子任务 3 (21 分)
- 1≤N≤100
- A=1
- 1≤B≤N
- 0≤Yi≤20
- 子任务 4 (25 分)
- 1≤N≤100
- 1≤A≤B≤N
- 0≤Yi≤1000000000
- 子任务 5 (29 分)
- 1≤N≤2000
- A=1
- 1≤B≤N
- 0≤Yi≤1000000000
时间限制:1s
空间限制:MB
#include<iostream> #include<cstdio> #include<cstring> #define maxn 110 using namespace std; int n,A,B,w[maxn],cnt; long long b[maxn],ans=1000000000000000LL; long long check(int sta){ long long res=0; cnt=1; b[1]=0; for(int i=1;i<n;i++){ b[cnt]+=w[i]; if(sta&(1<<(i-1))){ res|=b[cnt]; cnt++; b[cnt]=0; } if(cnt>B)return -1; } if(cnt<A)return -1; b[cnt]+=w[n]; res|=b[cnt]; return res; } int main(){ scanf("%d%d%d",&n,&A,&B); for(int i=1;i<=n;i++)scanf("%d",&w[i]); for(int i=0;i<(1<<(n-1));i++){ long long now=check(i); if(now!=-1) ans=min(ans,now); } cout<<ans<<endl; }
#include<iostream> #include<cstdio> #include<cstring> #define INF 0x3f3f3f3f #define maxn 2010 using namespace std; int f[105][105],g[maxn],n,A,B; long long a[maxn],sum[maxn],ans; void solve1(){ for(int pos=45;pos>=0;pos--){ memset(f,1,sizeof(f)); f[0][0]=0; for(int i=1;i<=n;i++) for(int j=1;j<=B;j++) for(int k=0;k<i;k++) if(f[k][j-1]==0 && (((sum[i]-sum[k])>>pos)&1)==0 && (((sum[i]-sum[k])|ans)>>pos)==(ans>>pos)){ f[i][j]=0; break; } bool flag=0; for(int i=A;i<=B;i++) if(f[n][i]==0){flag=1;break;} if(!flag)ans|=1LL<<pos; } cout<<ans<<endl; } void solve2(){ for(int pos=51;pos>=0;pos--){ for(int i=1;i<=n;i++)g[i]=INF; g[0]=0; for(int i=1;i<=n;i++) for(int j=0;j<i;j++){ if((((sum[i]-sum[j])>>pos)&1))continue; if((((sum[i]-sum[j])|ans)>>pos)==(ans>>pos)) g[i]=min(g[i],g[j]+1); } if(g[n]>B)ans|=1LL<<pos; } cout<<ans<<endl; } int main(){ scanf("%d%d%d",&n,&A,&B); for(int i=1;i<=n;i++){ cin>>a[i]; sum[i]=sum[i-1]+a[i]; } if(A==1)solve2(); else solve1(); return 0; }