#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
const int N = 1010;
int main() {
int t;
scanf("%d", &t);
while (t -- ) {
int n, m;
scanf("%d%d", &n, &m);
if (m == 1 && n > 1) {
printf("-1\n");
} else {
if (m == n) {
printf("1\n");
} else {
int res = 1;
n -= m;
res += n / (m - 1) * 2;
if (n % (m - 1) != 0) {
res += 2 ;
}
printf("%d\n", res);
}
}
}
return 0;
}
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int a[N];
int n, m;
int find() {
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (a[mid] >= m) {
r = mid;
} else {
l = mid + 1;
}
}
if (a[l] < m) {
return n;
} else {
return l;
}
}
int main() {
int t;
scanf("%d", &t);
while (t -- ) {
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ ) {
scanf("%d", &a[i]);
}
sort(a, a + n);
int k = find();
if (n % 2 == 0) {
if (k > n / 2 - 1) {
puts("-1");
} else {
printf("%d\n", n - 2 * k);
}
} else {
if (k > n / 2) {
puts("-1");
} else {
printf("%d\n", n - 2 * k);
}
}
}
return 0;
}
H. 牛牛看云
题意:给定n个数求:
∑
i
=
1
n
∑
j
=
i
n
∣
a
i
+
a
j
−
1000
∣
\sum_{i=1}^{n}\sum_{j=i}^{n}|a_i+a_j-1000|
∑i=1n∑j=in∣ai+aj−1000∣。
题解:去绝对值+总结公式,先将n个数排序,从前往后遍历
i
i
i每次二分找见
a
i
+
a
j
>
=
1000
a_i+a_j>=1000
ai+aj>=1000最小的
j
j
j,
j
j
j之前的数去绝对值后取反,j之后的数去绝对值为本身。
代码:
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int a[N], s[N];
int find(int k) {
int l = 1, r = k - 1;
int cp = 1000 - a[k];
while (l < r) {
int mid = l + r >> 1;
if (a[mid] >= cp) {
r = mid;
} else {
l = mid + 1;
}
}
if (a[l] < cp) {
return k;
} else {
return l;
}
}
int main() {
int n;
scanf("%d", &n);
LL res = 0;
for (int i = 1; i <= n; i ++ ) {
scanf("%d", &a[i]);
res += abs(2 * a[i] - 1000);
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i ++ ) {
s[i] = s[i - 1] + a[i];
}
for (int i = 2; i <= n; i ++ ) {
int k = find(i);
if (k == i) {
res += (i - 1) * (1000 - a[i]) - s[i - 1];
} else {
res += (i - 1 - k) * (a[i] - 1000) + s[i - 1] - s[k - 1];
res += (k - 2) * (1000 - a[i]) - s[k - 1];
}
}
printf("%lld\n", res);
return 0;
}
题解:若每一个人都唱"最优方案",反而最后一句话都唱不成,所以最优就应该是每个人都随机唱,对于每一句话每个人有
1
2
\frac{1}{2}
21的概率去唱,
1
2
\frac{1}{2}
21的概率不去唱,因此对于一句话来说唱失败的概率为:
(
1
2
)
n
+
(
1
2
)
n
(\frac{1}{2})^n+(\frac{1}{2})^n
(21)n+(21)n,唱成功的概率为:
1
−
(
1
2
)
n
−
(
1
2
)
1-(\frac{1}{2})^n-(\frac{1}{2})
1−(21)n−(21),对于m句话最后在乘m,最后的公式就是:
m
2
n
−
2
2
n
m\frac{2^n-2}{2^n}
m2n2n−2,最后在求个逆元就好。
代码:
#include <iostream>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
LL cal(LL a, int b) {
LL res = 1;
while (b) {
if (b & 1) {
res = res * a % mod;
}
a = a * a % mod;
b >>= 1;
}
return res;
}
int main() {
int t;
scanf("%d", &t);
while (t -- ) {
int n, m;
scanf("%d%d", &n, &m);
printf("%lld\n", (cal(2, n) - 2 + mod) % mod * cal(cal(2, n), mod - 2) % mod * m % mod);
}
return 0;
}
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long LL;
const int N = 1e4 + 10;
int a[N], b[N];
bool cmp(int a, int b) {
return a > b;
}
int main() {
int t;
scanf("%d", &t);
while (t -- ) {
int A, B, n;
scanf("%d%d%d", &A, &B, &n);
for (int i = 0; i < A; i ++ ) {
scanf("%d", &a[i]);
}
for (int j = 0; j < B; j ++ ) {
scanf("%d", &b[j]);
}
if (n - A > A) {
printf("-1\n");
} else {
sort(a, a + A, cmp);
sort(b, b + B, cmp);
LL res = 0;
int cnt = 0;
int i = 0, j = 0;
for (int k = 0; k < n; k ++ ) {
if (j == B) {
res += a[i ++ ];
} else if (i == A) {
res += b[j ++ ];
} else {
if (b[j] > a[i] && cnt < n / 2) {
cnt ++ ;
res += b[j ++ ];
} else {
res += a[i ++ ];
}
}
}
printf("%lld\n", res);
}
}
return 0;
}
L. 牛牛学走路
题意:从一个起点上下左右的走,求走的过程中距离起点的最大值。
题解:签到题,遍历就行。
代码:
#include <iostream>
#include <cmath>
using namespace std;
const int N = 1010;
char s[N];
int main() {
int t;
scanf("%d", &t);
while (t -- ) {
int n;
scanf("%d%s", &n, s);
int x = 0, y = 0;
double res = 0;
for (int i = 0; i < n; i ++ ) {
if (s[i] == 'U') {
y ++ ;
} else if (s[i] == 'D') {
y -- ;
} else if (s[i] == 'L') {
x -- ;
} else {
x ++ ;
}
res = max(res, sqrt(x * x + y * y));
}
printf("%.12lf\n", res);
}
return 0;
}