复健训练-CF1708(Codeforces Round #808 (Div. 2))

题目在这

 

A. Difference Operations

题意:给一个长为 n 的序列 $a_1 .. a_n$ ,对于 $i=2..n$ 可以执行任意多次 $a_i = a_i - a_{i-1}$ 。问最终能不能把 $a_2..a_n$ 都变成 0 。

做法:$a_1$ 不能动,$a_2$ 只有最终可以变为 $a_1$ 才可以成功变为 0 ,$a_3 .. a_n$ 也一样,最差情况是最终都可以通过 $-a_1$ 变成 0 。所以判断后面的数是否都为 $a_1$ 倍数即可。

#include<bits/stdc++.h>
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define ll long long
 
using namespace std;
 
const int N = 105;
int n, a[N];
 
void Main(){
    scanf("%d",&n);
    rep (i,1,n) scanf("%d", &a[i]);
    rep (i,2,n)
        if (a[i]%a[1]!=0){puts("NO"); return;}
    puts("YES");
    return;
}
 
int main(){
    int T;
    scanf("%d", &T);
    while (T--) Main();
    return 0;
}
View Code

 

B. Difference of GCDs

题意:给定 n, l, r ,要求构造一个长为 n 的序列 ${a}$ ,满足 $l \le a_i \le r$ 且 $\gcd(i,a_i)$ 互不相同。

做法:可以发现第 i 个 gcd 一定是 i 的一个因子,且 $gcd_1$ 一定是 1 ,那么 $gcd_2$ 不能是 1 只能是 2 ,$gcd_3$ 只能是 3 ,$gcd_4$ 不能是1, 2 只能是 4 ……依此类推发现第 i 个 gcd 必须是 i 。

所以就找到 $[l,r]$ 内 i 的倍数就可以了。

#include<bits/stdc++.h>
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define ll long long
 
using namespace std;
 
const int N = 1e5+10;
int n, l, r, a[N];
 
void Main(){
    scanf("%d%d%d", &n, &l, &r);
    rep (i,1,n){
        int t = r/i - (l-1)/i;
        if (t <= 0){puts("NO"); return;}
        a[i] = r/i * i;
    }
    puts("YES");
    rep (i,1,n) printf("%d ", a[i]);
    puts("");
}
 
int main(){
    int T; scanf("%d", &T);
    while (T --) Main();
    return 0;
}
View Code

 

C. Doremy's IQ

题意: n 场考试,第 i 场难度为 $a_i$ 。doremy要依次参加 n 场考试,初始 iq 为 $q$ ,当 $q > 0$ 时可以参加这场考试,如果 $a_i>q$ 那么 $q$ 要减一。问最多参加几场考试?构造方案。

做法:肯定是从后面部分开始降低 $q$ 划算,这样影响比较小。考虑假设最后刚好降到 $0$ 设为 $b_i$ ,一步步往前推,如果 $a_i > b_{i+1}$ $b_i$ 就 +1。相当于是保存了最后刚好降为 0 的 $q$ 最小值。然后最后只要看初始的 $q$ 是不是比每个 $b_i$ 或者 $a_i$ 大就可以了。

#include<bits/stdc++.h>
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define ll long long
 
using namespace std;
 
const int N = 1e5+10;
int n, Q, a[N], b[N];
 
void Main(){
    scanf("%d%d", &n, &Q);
    rep (i,1,n) scanf("%d", &a[i]);
    int w = 0;
    for (int i=n;i>=1;i--){
        if (a[i]>w) w++;
        b[i] = w;
    }
    int ans = 0;
    rep (i,1,n)
        if (Q >= min(b[i], a[i])) cout<<1; else cout<<0;
    puts("");
    return;
}
 
int main(){
    int T; scanf("%d", &T);
    while (T--) Main();
    return 0;
}
View Code

 

D. Difference Array

题意:给一个数组,每次排序后做差分,问最后 $a_1$ 是多少。

做法:暴力+剪枝就可以了,但还是不知道为啥复杂度是对的 www ,题解在这

#include<bits/stdc++.h>
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
using namespace std;
 
const int N=1e5+10;
int n, a[N];
 
void Main(){
    scanf("%d", &n);
    rep (i,1,n) scanf("%d", &a[i]);
    for (int i=n-1; i>=1; i--){
        int pre = a[i+1], ok = 0;
        for (int j = i; j>=1; j --){
            ok = a[j] == 0;
            pre -= (a[j] = pre - a[j]);
            if (ok){sort(a+j, a+i+1); break;}
        }
        if (!ok) sort(a+1, a+i+1);
    }
    printf("%d\n", a[1]);
    return;
}
 
int main(){
    int T; scanf("%d", &T);
    while (T--) Main();
    return 0;
}
View Code

 

E F 咕咕咕

posted @ 2022-07-17 12:01  bestfy  阅读(67)  评论(0编辑  收藏  举报