复健训练-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; }
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; }
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; }
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; }
E F 咕咕咕