// y总题解奉上 #include<iostream> #include<cstdio> usingnamespacestd; constint N = 100010; int num[N]; // num[0]默认为0 int n; boolcheck(int m){ for (int i = 1;i <= n;i ++){ m = 2*m - num[i]; if (m >= 1e5) returntrue; // E >= max h,提前退出 if (m < 0) returnfalse; } returntrue; // 这里别忘了 } intmain(){ scanf("%d",&n); // 从num[1]开始读,包括num[0]在内是n+1座建筑 for (int i = 1;i <= n;i++) scanf("%d",&num[i]); int l = 0,r = 1e5; while (l < r){ int mid = (l+r)/2; if (check(mid))r = mid; else l = mid + 1; } printf("%d",l); return0; }
算法二:公式法。(本人原创)
设跳到第 k 座建筑后的能量为a[k],有递推关系:a[k] = 2*a[k-1] - h[k], k >= 1
constint N = 2500010; // 5*10^6的一半,后面枚举c、d structSum{ int s,c,d; // 结构体排序,重载小于号 booloperator< (const Sum& t) const { if (s != t.s) return s < t.s; // s、c、d按字典序排序 if (c != t.c) return c < t.c; return d < t.d; } }sum[N];
int n,m; intmain(){ scanf("%d",&n); for (int c = 0;c*c<= n;c++) for (int d = c;c*c+d*d<= n;d++) { sum[m++] = {c*c+d*d,c,d}; } sort(sum,sum+m);
for (int a = 0;a*a<= n;a++) for(int b = a;a*a+b*b<= n;b++) { int t = n-a*a-b*b; int l = 0,r = m-1; while (l < r){ int mid = (l+r) >> 1; if (sum[mid].s >= t) r = mid; else l = mid + 1; } if (sum[l].s == t){ printf("%d %d %d %d",a,b,sum[l].c,sum[l].d); return0; } } return0; }
for (int c = 0; c * c <= n; c ++ ) for (int d = c; c * c + d * d <= n; d ++ ) { int t = c * c + d * d; if (S.count(t) == 0) S[t] = {c, d}; }
for (int a = 0; a * a <= n; a ++ ) for (int b = 0; a * a + b * b <= n; b ++ ) { int t = n - a * a - b * b; if (S.count(t)) { printf("%d %d %d %d\n", a, b, S[t].x, S[t].y); return0; } }