A、牛牛的三角形
方法一,枚举第一二三个点,判断任意两边之和都要大于第三边,时间复杂度
#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
using namespace std;
inline ll read() {
ll s = 0, w = 1; char ch = getchar();
while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s * w;
}
const int N = 1e2 + 7;
int a[N];
bool check(int a, int b, int c) {
if (a + b > c && a + c > b && b + c > a) return true;
return false;
}
int main() {
int n = read();
for (int i = 1; i <= n; ++i) a[i] = read();
for (int i = 1; i < n - 1; ++i)
for (int j = i + 1; j < n; ++j)
for (int k = j + 1; k <= n; ++k) if (check(a[i] , a[j] , a[k])) {
printf("%lld %lld %lld", a[i], a[j], a[k]);
return 0;
}
puts("No solution");
return 0;
} 方法二:先排序,再把连续的三个点判断,如果当前的三个升序数字不行,那么在后面一个数字,会比前面任何一个都大,更不满足任意两边大于第三边,放弃最前面最小的点。时间复杂度
#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
using namespace std;
inline int read() {
int s = 0, w = 1; char ch = getchar();
while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s * w;
}
const int N = 1e2 + 7;
int num[N];
bool check(int a, int b, int c) {
if (a + b > c && a + c > b && b + c > a) return true;
return false;
}
int main() {
int n = read();
for (int i = 1; i <= n; ++i) num[i] = read();
sort(num+1,num+1+n);
for (int i = 1; i + 2 <= n; ++i) {
if (check(num[i], num[i + 1], num[i + 2])) {
printf("%d %d %d", num[i], num[i + 1], num[i + 2]);
return 0;
}
}
puts("No solution");
return 0;
} B、牛牛的鱼缸
鱼缸中的水只有2种状态,第一三角形,第二直角梯形。
先通过三角形相似,算出鱼缸如果没有阻挡的底记为x,如果这个底小于等于真正的底,直接按三角形计算即可。
如果大于,按照梯形公式,下底是给定的h,上底通过x-l和相似算得,高就是l。
#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
typedef long long ll;
inline int read() {
int s = 0, w = 1; char ch = getchar();
while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s * w;
}
const int N = 1e2 + 7;
const int MOD = 1e9 + 7;
int main() {
double h = read(), l = read(), H = read(), L = read();
scanf("%lf%lf%lf%lf", &h, &l, &H, &L);
double sl = h * L / H;
if (sl <= l) {
printf("%.8f\n", sl * h / 2);
}
else {
double sh = H * (sl - l) / L;
printf("%.8f\n", l * (sh + h) / 2);
}
return 0;
} C、牛牛的揠苗助长
二分+最小操作数
第一次拿到这个题目,我第一时间想法是枚举终点,二分天数,再去二分的时候跑最小,这样分析下来时间复杂度竟然到了
那我们必须换思路,或者改进算法。这个时候,我看到题目,我们如果二分天数的时候,如果对n取模,不就是确定了终点么?为什么还要去枚举终点。
所以这个地方除掉N的复杂度,总的复杂度就是
接下来就是二分法check函数的设计了,因为终点确定了,那我们知道,无论你多跑多少个轮回,中间轮回都是没用的,因为全部加一,看成全部不变就行了。
那么我们用一个a保持初始的高度,另开一个b保存在终点之前(包括终点)可以被额外高度加一的顶点和后序未被递增的顶点高度。
这个时候,问题就来到了如何通过这样的高度,找到最优解的高度。最终吧最优解高度下,和二分天数判断一下就行了。
我们知道,如果我们保证b有序(假设升序),如果b的点数是奇数,那么一定是中间的一个点高度下,花费最小。(下面配图)
如果b是偶数,中间两个点,假设高度是x4和x5,那么在 [x4,x5]中的全部高度,算到的答案都是一样的,并且最短,可以类比奇数情况(下面配图)
所以综上,在升序数组b中,按中位数(偶数取到左边高度或者右边高度不影响答案)节点的高度为最优解即可。
#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
typedef long long ll;
inline int read() {
int s = 0, w = 1; char ch = getchar();
while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s * w;
}
const int N = 1e5 + 7;
const int MOD = 1e9 + 7;
ll a[N], b[N];
int n;
bool check(ll p) {
ll sum = 0, mini = 1e18;
for (int i = 1; i <= n; ++i) b[i] = a[i] + p / n + (p % n >= i ? 1 : 0);
sort(b + 1, b + 1 + n);
ll num1 = b[(n >> 1)+1];
ll ans = 0;
for (int i = 1; i <= n; ++i)
ans += abs(b[i] - num1);
return ans <= p;
}
int main() {
n = read();
for (int i = 1; i <= n; ++i) a[i] = read();
ll l = 0, r = 1e18, ans = 0;
while (l <= r) {
ll mid = r + l >> 1;
if (check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%lld\n", ans);
return 0;
} 
京公网安备 11010502036488号