目录
Problem A. 数位重排 (100)
有两种解决方案
(I)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
char s1[110];
int arr[110], n;
scanf("%s", s1);
n = strlen(s1);
for (int i = 0; i < n; i++)
arr[i] = s1[i] - '0';
next_permutation(arr, arr + n);
for (int i = 0; i < n; i++)
printf("%d", arr[i]);
return 0;
}
(II)
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
char s1[110];
int arr[110];
scanf("%s", s1);
int n;
n = strlen(s1);
for (int i = 0; i <= n; i++)
arr[i] = s1[i] - '0';
int bj = 0;
for (int i = n - 2; i >= 0; i--)
{
if (arr[i] < arr[i + 1])
{
bj = i;
break;
}
}
for (int i = n - 1; i > bj; i--)
{
if (arr[bj] < arr[i])
{
swap(arr[bj], arr[i]);
break;
}
}
sort(arr + bj + 1, arr + n);
for (int i = 0; i < n; i++)
printf("%d", arr[i]);
return 0;
}
Peoblem B.小青蛙找眼镜
解决方法:使得跳跃到达的位置与目标位置的差为偶数即可
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
long long q, x, n;
scanf("%lld", &q);
while (q--)
{
scanf("%lld", &x);
x = fabs(x);
n = sqrt(2 * x);
while (n * (n + 1) / 2 < x)
n++;
while ((n * (n + 1) / 2 - x) % 2 != 0)
n++;
printf("%lld\n", n);
}
return 0;
}
Peoblem C.数七
简单查找即可
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
long long n;
int n1;
bool yo = false;
scanf("%lld", &n);
if (n % 7 == 0)
printf("Yes\n");
else
{
while (n >= 10)
{
if (n % 10 == 7)
{
yo = true;
break;
}
n = n / 10;
}
if (yo == true || n == 7)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
Peoblem D. 宝石
解决方法:枚举对称轴与对称半径即可
#include<iostream>
const int N = 5010;
using namespace std;
int main()
{
int v[N], w[N];
int n;
int sum1 = 0, d, sum2, ans = 0, l, r;
double k;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &v[i]);
for (int i = 1; i <= n; i++)
scanf("%d", &w[i]);
for (int i = 1; i <= n; i++)
{
sum1 += v[i] * w[i];
d = sum2 = 0;
for (int j = 1; j <= n / 2; ++j)
{
if (i - j < 1 || i + j > n)
break;
l = i - j;
r = i + j;
sum2 += v[l] * w[l] + v[r] * w[r];
d += v[l] * w[r] + v[r] * w[l];
ans = max(ans, d - sum2);
}
sum2 = d = 0;
for (int j = 1; j <= n / 2; ++j)
{
if (j > i || i + j > n)
break;
l = i - j + 1;
r = i + j;
sum2 += v[l] * w[l] + v[r] * w[r];
d += v[l] * w[r] + v[r] * w[l];
ans = max(ans, d - sum2);
}
}
printf("%d", sum1 + ans);
return 0;
}
Peoblem E. 最短子序列
解决方法:枚举左右边界即可
如L[r]与l的差值为左半边的区间大小
R[l]与r的差值为右半边区间的大小
#include<iostream>
using namespace std;
const int N = 1e6 + 10;
const int inf = 0x3f3f3f3f;
int L[N], Rmin[N], R[N];
int a[N];
int main()
{
int n;
long long k;
scanf("%d %lld", &n, &k);
for (int i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);
}
int l = 1;
int sum1 = 0;
for (int r = 1; r <= n; ++r)
{
sum1 += a[r];
while (l <= r && sum1 - a[l] >= k)
sum1 -= a[l++];
if (l <= r && sum1 == k)
L[r] = l;
else
L[r] = -inf;
}
int r = n;
sum1 = 0;
Rmin[n + 1] = inf;
for (int l = n; l >= 1; --l)
{
sum1 += a[l];
while (l <= r && sum1 - a[r] >= k)
sum1 -= a[r--];
if (l <= r && sum1 == k)
R[l] = r;
else
R[l] = inf;
Rmin[l] = min(Rmin[l + 1], R[l] - l + 1);
}
int ans = inf;
for (int i = 1; i <= n; ++i)
ans = min(ans, i - L[i] + 1 + Rmin[i + 1]);
if (ans > n)
ans = -1;
printf("%d", ans);
return 0;
}
Peoblem F. 分糖果
解决方法:只需要知道糖果多出来的部分与不够的部分总和,再知道可以多分的糖果与可以要糖果的部分总值即可解决
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
int n, k, l1, l2, l = -1;
long cnt = 0, sum1 = 0, sum2 = 0, h1 = 0, h2 = 0;
bool y = false;
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; i++)
{
y = false;
scanf("%d %d", &l1, &l2);
if (l1 > k)
{
sum1 += l1 - k;//缺
}
else if (l2 < k)
{
h1 += k - l1 + (l2 - k);//h1代表可以多出
}
else
h1 += k - l1;
if (l2 < k)
{
sum2 += k - l2;//多
}
else
h2 += l2 - k;//h2代表可以放入
if (y == true)
{
h2 += k - l1;
}
}
cnt = sum2;
if (sum2 == sum1)
{
printf("%ld\n", cnt);
}
else if (sum2 > sum1)
{
if (h2 >= sum2 - sum1)
{
printf("%ld\n", cnt);
}
else
printf("%d\n", l);
}
else
{
if (h1 >= sum1 - sum2)
{
cnt = sum1;
printf("%ld\n", cnt);
}
else
printf("%d\n", l);
}
return 0;
}