Codeforces Round #701 (Div. 2) A~D题解
A. Add and Divide
-
题意
给定整数 a , b a,b a,b,你每次可以进行两种操作:- a = ⌊ a b ⌋ a=\lfloor\frac{a}{b}\rfloor a=⌊ba⌋。
- b = b + 1 b = b+1 b=b+1。
问最小的操作次数使得 a = 0 a = 0 a=0。
-
解题思路
我们知道, 2 30 > 1 0 9 2^{30}>10^9 230>109,所以如果 b = 2 b =2 b=2,那么进行操作 1 1 1, a a a可以在不超过 30 30 30次操作将 a a a变为 0 0 0。那么意味着 b b b的变化不会超过 31 31 31次。我们枚举 b b b,然后统计所需的次数取最小值即可。 -
AC代码
/**
*@filename:A
*@author: pursuit
*@created: 2021-09-06 19:05
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int t, a, b;
void solve(){
int minn = INF;
for(int i = max(b, 2); i <= b + 31; ++ i){
int temp = a, cnt = i - b;
while(temp){
temp /= i;
++ cnt;
}
minn = min(cnt, minn);
}
cout << minn << endl;
}
int main(){
cin >> t;
while(t -- ){
cin >> a >> b;
solve();
}
return 0;
}
B. Replace and Keep Sorted
-
题意
给你一个 n n n个整数的序列 a a a,有 q q q次查询,每次查询给出 [ l , r ] [l,r] [l,r],即通过 a l ⋯ a r a_l\cdots a_r al⋯ar形成一个新序列 c c c,需要你找出有多少数组 b b b为 c c c的 k k k相似:即满足严格递增;与 c c c恰好存在一位不同;每个元素取值范围为 [ 1 , k ] [1,k] [1,k];具有相同的长度 r − l + 1 r - l + 1 r−l+1。 -
解题思路
我们知道,如果要满足严格递增,那么不是端点的 a [ i ] a[i] a[i]只能变化于 [ a [ i − 1 ] , a [ i ] ) [a[i-1],a[i]) [a[i−1],a[i])和 ( a [ i ] , a [ i + 1 ] (a[i],a[i+1] (a[i],a[i+1],处于左端点的 a [ i ] a[i] a[i]可以变化于 [ 1 , a [ i ] ) [1,a[i]) [1,a[i]),处于右端点的 a [ i ] a[i] a[i]可以变化于 ( a [ i ] , k ] (a[i],k] (a[i],k]。所以我们可以统计出相邻两数的变化次数,即 d i f f [ i ] = a [ i ] − a [ i − 1 ] − 1 diff[i] = a[i] - a[i-1]-1 diff[i]=a[i]−a[i−1]−1,然后我们发现数的变化如图:

易知 [ l , r ] [l,r] [l,r]的相邻两数变化的区间都被用了两次,我们可以先处理出前缀和 s u m [ r ] sum[r] sum[r]表示 [ 1 , r ] [1,r] [1,r]中的变化次数总和,那么对于 [ l , r ] [l,r] [l,r]由于 a [ i ] a[i] a[i]到 a [ i + 1 ] a[i+1] a[i+1]的变化用了两次,所以这里需要计算 ( s u m [ r ] − s u m [ l ] ) × 2 (sum[r]-sum[l])\times 2 (sum[r]−sum[l])×2,然后 a [ l ] , a [ r ] a[l],a[r] a[l],a[r]的变化需要累加 a [ l ] − 1 + k − a [ r ] a[l]-1+k-a[r] a[l]−1+k−a[r]。
至此题解。 -
AC代码
/**
*@filename:B
*@author: pursuit
*@created: 2021-09-07 09:35
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int n, q, k, a[N], diff[N], sum[N];
void solve(){
int l, r;
while(q -- ){
scanf("%d%d", &l, &r);
//l 和 r可以往l - 1和r + 1那靠。
int x = (sum[r] - sum[l]) * 2;
x += a[l] - 1 + k - a[r];
printf("%d\n", x);
}
}
int main(){
scanf("%d%d%d", &n, &q, &k);
for(int i = 1; i <= n; ++ i){
scanf("%d", &a[i]);
diff[i] = a[i] - a[i - 1] - 1;//判断可供选择空间。
sum[i] = sum[i - 1] + diff[i];
}
solve();
return 0;
}
C. Floor and Mod
- 题意
给定 a a a和 b b b的范围为 a ∈ [ 1 , x ] , b ∈ [ 1 , y ] a\in[1,x],b\in[1,y] a∈[1,x],b∈[1,y],求有多少对 ( a , b ) (a,b) (a,b)使得 a / b = a m o d b a/b=a\mod b a/b=amodb。 - 解题思路
我们设 a / b = a m o d b = k a/b=a\mod b =k a/b=amodb=k,那么 a = k b + k = k × ( b + 1 ) a=kb+k=k\times(b+1) a=kb+k=k×(b+1)。则任务转变为对于每个 b b b找到有多少个 k k k满足 k × ( b + 1 ) = a k \times (b + 1) = a k×(b+1)=a的。由于余数为 k k k,所以 b > k b > k b>k,因为余数不会超过b。那么我们可以枚举 k k k,然后通过 a a a的取值范围可得到 b b b的取值范围为 x / k − 1 x/k-1 x/k−1,又因为要大于 k k k,则 b b b的取值范围为 m i n ( y , x / k − 1 ) − k min(y,x/k-1)-k min(y,x/k−1)−k。
故此题得解, - AC代码
/**
*@filename:C
*@author: pursuit
*@created: 2021-09-07 09:49
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int t, x, y;
void solve(){
int temp = sqrt(x);
ll sum = 0;
for(int k = 1; k <= temp; ++ k){
//- k是因为b > k。
sum += max(0, min(y, x / k - 1) - k);
}
printf("%lld\n", sum);
}
int main(){
cin >> t;
while(t -- ){
cin >> x >> y;
solve();
}
return 0;
}
D. Multiples and Power Differences
-
题意
给定矩阵 a a a,然后让你构造相同大小的 b b b。使得: b i j ∈ [ 1 , 1 0 6 ] b_{ij} \in [1,10^6] bij∈[1,106]; b i j b_{ij} bij为 a i j a_{ij} aij的倍数。对于每个相邻的单元格对中数字之间的差值的绝对值为 k 4 k^4 k4。 -
解题思路
由于 a i , j ∈ [ 1 , 16 ] a_{i,j}\in[1,16] ai,j∈[1,16],所以 l c m i = 1 16 i = 720720 ≤ 1 0 6 lcm_{i=1}^{16}i=720720\leq 10^6 lcmi=116i=720720≤106。则我们可以在奇数位置构造该值,然后偶数位置都构造 720720 + a i j 4 720720+a_{ij}^4 720720+aij4。至此,相邻两数之差则满足。 -
AC代码
/**
*@filename:D
*@author: pursuit
*@created: 2021-09-07 10:18
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 5e2 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int n, m, a[N][N];
void solve(){
int lcm = 1;
for(int i = 2; i <= 16; ++ i){
lcm = i * lcm / __gcd(i, lcm);
}
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= m; ++ j){
if((i + j) & 1){
printf("%d ", lcm);
}
else{
printf("%d ", lcm + (int)pow(a[i][j], 4));
}
}
puts("");
}
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= m; ++ j){
scanf("%d", &a[i][j]);
}
}
solve();
return 0;
}

浙公网安备 33010602011771号