A
A. K-divisible Sum
题意:给两个数字n,k,构造一个有n个数的数组使得数组的总和可以整除k,且要使这个数组中的每个数尽可能的小,输出数组中的最大值。
分情况讨论:
如果n >= k;
1.如果n能整除k,那么n个数全为1即可
2.如果n不能整除k,那么1和2也能构造成功
如果n < k;
那么数的取值级为 k / n 的上取整
在整数上取整中,例子:ceil(k / n) = (k + n - 1) / n
代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int T, n, k;
void solve() {
cin >> n >> k;
if(n >= k) {
if(n % k == 0) cout << 1 << '\n';
else cout << 2 << '\n';
} else cout << (k + n - 1) / n << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> T;
while(T--) solve();
return 0;
}
B
题目大意:
一种产品的价格变化统计数据用n个正整数的数组表示,
p
0
,
p
1
,
p
2
.
.
.
p
n
−
1
p_0,p_1,p_2...p_{n-1}
p0,p1,p2...pn−1,其中
p
0
p_0
p0是产品的初始价格,
p
i
p_i
pi是第i个月的价格增长情况。使用这些价格变化要求你计算每个月的通货膨胀系数:
(
p
0
+
p
1
+
p
2
.
.
.
+
p
i
−
1
)
/
p
i
(p_0 + p_1 + p_2 ... + p_{i - 1}) / p_i
(p0+p1+p2...+pi−1)/pi。你需要保证每个月的通货膨胀系数不超过百分之k,你需要增加
p
i
p_i
pi的值,使之成立,问最少增加多少。
题解:
一个显然的条件:直接增加
p
0
p_0
p0即可,因为所有的通货膨胀系数的分母均含有
p
0
p_0
p0,因此增加
p
0
p_0
p0即可。
假设增加的值为x,那么需要满足该公式成立
p
i
/
(
p
0
+
p
1
+
p
2
+
.
.
.
+
p
i
−
1
+
x
)
<
=
k
/
100
p_i / (p_0 + p_1 + p_2 + ... + p_{i - 1} + x) <= k / 100
pi/(p0+p1+p2+...+pi−1+x)<=k/100
100
∗
p
i
<
=
k
∗
(
p
0
+
p
1
+
p
2
+
.
.
.
+
p
i
−
1
+
x
)
100 * p_i <= k * (p_0 + p_1 + p_2 + ... + p_{i - 1} + x)
100∗pi<=k∗(p0+p1+p2+...+pi−1+x)
100
∗
p
i
−
k
∗
(
p
0
+
p
1
+
p
2
+
.
.
.
+
p
i
−
1
)
<
=
k
∗
x
100 * p_i - k * (p_0 + p_1 + p_2 + ... + p_{i - 1} ) <= k * x
100∗pi−k∗(p0+p1+p2+...+pi−1)<=k∗x
最后得出
x
>
=
c
e
i
l
(
[
100
∗
p
i
−
k
∗
(
p
0
+
p
1
+
p
2
+
.
.
.
+
p
i
−
1
)
]
/
k
)
x >= ceil([100 * p_i - k * (p_0 + p_1 + p_2 + ... + p_{i - 1} ) ] / k)
x>=ceil([100∗pi−k∗(p0+p1+p2+...+pi−1)]/k)
从头开始遍历,找到最大的满足条件即可
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int T, n, k;
typedef long long ll;
const int N = 110;
ll p[N];
void solve() {
cin >> n >> k;
for(int i = 1; i <= n; i++) cin >> p[i];
ll res = 0, sum = p[1];
for(int i = 2; i <= n; i++) {
res = max(res, (100ll * p[i] - sum * k + k - 1) / k);
sum += p[i];
}
cout << res << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> T;
while(T--) solve();
return 0;
}
C
找到最大的环。
类似于数组里最大的子序列问题
但是在dp转移的时候需要进行一下特判,如果当前已经形成环了,那么不在进行转移。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 100010;
int n, T;
int a[N], b[N];
long long dp[N];
void solve() {
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> dp[i];
dp[i]--;
//初始dp[i]的长度为c[i]的长度
}
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++) cin >> b[i];
long long res = 0;
for(int i = n; i > 1; i--) {
int d = abs(a[i] - b[i]);
res = max(dp[i] + d + 2, res);
if(d) dp[i - 1] = max(dp[i] + 2 + dp[i - 1] - d, dp[i - 1]); //如果当前两点相交,那么就已经构成环了,不能再想前转移
}
cout << res << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> T;
while(T--) solve();
return 0;
}
D
D. Journey
由于走完一条路后,所有的路的方向会变反,那么假如说当前的坐标是x
如果x可以向左走,那么向左走的最长长度为LRLR…交替的字符串的长度
如果x可以向右走,那么向右走的最长长度为RLRL…交替的字符串的长度
这两个可以预处理出来
代码如下:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 300010;
int n, T;
char str[N];
int r[N], l[N];
void solve() {
cin >> n;
cin >> str + 1;
int size = strlen(str + 1);
for(int i = 1; i <= size; ) {
int j = i; //j 是终点
while(j + 1 <= size && str[j + 1] != str[j])
j++;
for(int k = i - 1; k < j; k++)
if(str[k + 1] == 'R') r[k] = j - k + 1;
else r[k] = 1;
i = j + 1;
}
for(int i = size; i >= 1; ) {
int j = i; //j - 1是终点
while(j - 1 >= 1 && str[j - 1] != str[j])
j--;
for(int k = i; k >= j; k--)
if(str[k] == 'L') l[k] = k - j + 2;
else l[k] = 1;
i = j - 1;
}
for(int i = 0; i <= n; i++) {
if(!i) cout << r[i] << ' ';
else if(i == n) cout << l[i] << ' ';
else cout << r[i] + l[i] - 1 << ' ';
}
cout << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> T;
while(T--) solve();
return 0;
}