2 条题解
-
0
二分,搜索,dp等常用算法可以尝试是否可行
二分答案将“直接求出答案”变成“判定答案是否可行”(感觉也是一种正难则反)
我们可以n^2暴力check
bool check(int x){ int c[60],b[60],d[60]; memcpy(c,a,sizeof a); memset(b,0,sizeof b); b[0]=x; for(int i=1;i<=n;i++){ memset(d,0,sizeof d); for(int j=0;j<n-1;j++){ if(b[j]>c[i]){ d[j+1]+=c[i],b[j]-=c[i],c[i]=0;break; } else d[j+1]+=b[j],c[i]-=b[j],b[j]=0; } for(int j=0;j<=n-1;j++) b[j]+=d[j]; } return b[n-1]==x; }当然也有n的做法:
把n种珠子填到x个项链中(一种珠子对一条项链最多只能造成1的贡献),若 最后x个项链中都有>=n-1个珠子 则合法,
其中珠子有个数限制,我们发现这是关键矛盾
那么尝试先不管个数限制,给x条项链都填上n个珠子,然后再把不够的珠子删掉
sum记录有多少珠子减了1
for(int i=1;i<=n;i++){ sum+=max(0,x-a[i]); } return sum<=x; -
0
这道题的难点:想到二分
先审一遍题,发现可以这么处理:先造出 个恰好包含 颗珠子的项链,(不难看出这个 就是 )再归还 颗珠子,使得剩下的珠子能够造出最多的恰好包含 颗珠子的项链,设为 。
具体实现:先把所有的 从小到大排序,这样最小值便是 ,将所有的 减去这个最小值,这样 就会变为 ,之后我们就不用管它了。归还 颗珠子的时候,只需要考虑 到 就行了。考虑具体如何归还,注意到, 的最大值其实就是归还完后 到 的最小值,由于具体归还策略比较难考虑,可以二分答案。
下面是代码:
#include<bits/stdc++.h> using namespace std; long long a[59]; long long n; bool flag=0; bool check(long long x,long long sum){ for(long long i=2;i<=n;i++)//check逻辑:如果归还sum颗珠子能够支持再造x个包含n-1颗珠子的项链,返回1,否则返回0 if(a[i]<x) if(x-a[i]>sum) return 0; else sum-=x-a[i]; return 1; } int main(){ scanf("%lld",&n); for(long long i=1;i<=n;i++) scanf("%lld",&a[i]); sort(a+1,a+n+1); long long sum=a[1]; for(long long i=1;i<=n;i++)//先造sum个包含n颗珠子的项链 a[i]-=sum; long long l=0,r=1000000000;//二分上界其实没那么大,不过我懒得改了 while(l+1<r){//二分答案 long long mid=(l+r)>>1; if(check(mid,sum)) l=mid; else r=mid; } printf("%lld\n",l+sum); return 0; }整体复杂度O(nlogn)
- 1
信息
- ID
- 278
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- (无)
- 递交数
- 12
- 已通过
- 6
- 上传者