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 alar形成一个新序列 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 rl+1

  • 解题思路
    我们知道,如果要满足严格递增,那么不是端点的 a [ i ] a[i] a[i]只能变化于 [ a [ i − 1 ] , a [ i ] ) [a[i-1],a[i]) [a[i1],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[i1]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+ka[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/k1,又因为要大于 k k k,则 b b b的取值范围为 m i n ( y , x / k − 1 ) − k min(y,x/k-1)-k min(y,x/k1)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=720720106。则我们可以在奇数位置构造该值,然后偶数位置都构造 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;
}
posted @ 2022-03-26 16:48  unique_pursuit  阅读(25)  评论(0)    收藏  举报