二分答案,考虑二分背包中的最大值是多少。
枚举 \(p\) 的值,在当前最优答案不优时,直接跳掉。
随机化一下 \(p\),这样复杂度会有保证。
#include<bits/stdc++.h> #define ri register signed #define p(i) ++i namespace IO{ char buf[1<<21],*p1=buf,*p2=buf; #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++ struct nanfeng_stream{ template<typename T>inline nanfeng_stream &operator>>(T &x) { ri f=1;x=0;register char ch=gc(); while(!isdigit(ch)) {if (ch=='-') f=0;ch=gc();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=gc();} return x=f?x:-x,*this; } }cin; } using IO::cin; namespace nanfeng{ #define FI FILE *IN #define FO FILE *OUT template<typename T>inline T cmax(T x,T y) {return x>y?x:y;} template<typename T>inline T cmin(T x,T y) {return x>y?y:x;} static const int N=1e4+7; int a[N],tmp[N],p[N],ans,n,P,k; inline int check(int mid) { ri cnt(0),nw(0); for (ri i(1);i<=n;p(i)) { if (tmp[i]>mid) return 0; if (nw+tmp[i]>mid) p(cnt),nw=0; nw+=tmp[i]; } return cnt<k; } inline int MD(int x) {return x>=P?x-P:x;} inline int main() { //FI=freopen("nanfeng.in","r",stdin); //FO=freopen("nanfeng.out","w",stdout); srand(time(0)*clock()^time(0)*clock()); cin >> n >> P >> k; for (ri i(1);i<=n;p(i)) cin >> a[i]; for (ri i(1);i<=P;p(i)) p[i]=i-1; std::random_shuffle(p+1,p+P+1); ans=10000*n; for (ri i(1);i<=P;p(i)) { ri cp=p[i]; for (ri j(1);j<=n;p(j)) tmp[j]=MD(a[j]+cp); if (!check(ans)) continue; ri l(0),r(ans),res; while(l<=r) { int mid(l+r>>1); if (check(mid)) r=mid-1,res=mid; else l=mid+1; } ans=res; } printf("%d\n",ans); return 0; } } int main() {return nanfeng::main();}