CF补题 993-Div.4-20241221
Dashboard - Codeforces Round 993 (Div. 4) - Codeforces
A:
题目大意:给出一个 \(n\) ,求有多少有序正整数数对 \((a,b)\),使得 \(a=n-b\)
#include <iostream>
#define streampreset() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;int main()
{streampreset();int T;cin >> T;while (T--){int n;cin >> n;cout << n - 1 << endl;}return 0;
}
经典数学小知识
B:
题目大意:给出一个由 p,q,w
组成的字符串,求它的镜像串
#include <iostream>
#include <string>
#define streampreset() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;int main()
{streampreset();int T;cin >> T;while (T--){string a;cin >> a;for (int i = a.size() - 1; i >= 0; i--) {if (a[i] == 'q') cout << 'p';else if (a[i] == 'p') cout << 'q';else cout << a[i];}cout << endl;}return 0;
}
正序输入,倒序输出,p,q
翻转 w
不变
C:
题目大意:\(2*m\) 个座位有 \(a+b+c\) 只猴子,\(a\) 猴子只能坐第一排, \(b\) 猴子只能坐第二排,\(c\) 猴子随便坐,求最大能坐下的猴子数
#include <iostream>
#include <algorithm>
#define streampreset() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;int main()
{streampreset();int T;cin >> T;while (T--){int m, a, b, c;int ans = 0;cin >> m >> a >> b >> c;ans+=min(a,m);ans+=min(b,m);ans+=min(2*m-min(a,m)-min(b,m),c);cout<<ans<<endl;}return 0;
}
贪心,首先安排 \(a,b\) 猴子,剩下的座位就是 \(c\) 猴的
D:
题目大意:给出一个序列a
,构造一个序列b
使得 \(a_i\) 是 \(1\le i \le n\) 上的 \([b_1,b_2...b_i]\) 的模,模指的是一个序列中出现次数最多的数(众数)
#include <iostream>
#define streampreset() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;int a, st[200010];
int n;int main()
{streampreset();int T;cin >> T;while (T--){memset(st, 0, sizeof st);cin >> n;int d = 1;for (int i = 1; i <= n; i++) {cin >> a;while (st[d]) d++;//定位if (st[a]) {cout << d << ' ';//如果出现过,就填dst[d]++;}else {cout << a << ' ';没有出现过,就填ast[a]++;}}cout << endl;}return 0;
}
脑筋急转弯,只要我们保证每次出现的数都不重复,即每个数都只出现一次,那么所有的数都是这个序列的模
所以我们维护一个状态序列,每次判断当前的 \(a_i\) 是否出现过,如果出现过,就使 \(b_i\) 为一个从未出现过的数,如果没有出现过,我们就把他加入序列
每次循环前,都要将d
定位到没有出现过的数上
E:
题目大意:对 \(x,y\) 两个正整数,给定两个区间 l1,r1,l2,r2
和一个底数 k
,求满足 \(\frac{y}{x}=k^n\) 的 \((x,y)\) 有序对数
#include <iostream>
#include <algorithm>
#include <math.h>
#define streampreset() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
using namespace std;int main()
{streampreset();int T;cin >> T;while (T--){long long k, la, ra, lb, rb;cin >> k >> la >> ra >> lb >> rb;long long sum = 1;long long ans = 0;long long u, v;while (sum <= rb) {long long i = la - 1, j = ra + 1;while (i + 1 != j){long long mid = (i + j) >> 1;if (mid * sum >= lb) j = mid;//else i = mid;}u = j;//取分界右侧i = la - 1, j = ra + 1;while (i + 1 != j){long long mid = (i + j) >> 1;if (mid *sum > rb) j = mid;else i = mid;}v = i;//取分界左侧if (u <= v) ans += v - u + 1;sum *= k;}cout << ans << endl;}return 0;
}
\(\frac{y}{x}=k^n\) 可变形为 \(y=x*k^n\), \(x=\frac{y}{k^n}\) ,我们已知 \(x,y\) 的取值范围,通过枚举 \(n\) 再二分查找 \(x\) 的边界
枚举 \(n\) 只需要枚举到 \(k^n\le y_{max}\) ,因为超过界限后,左右边界都为 \(0\) 无意义
二分找 \(x\) 的边界,分别求满足 \(x*k^n=y_{min}\) 和 \(x*k^n=y_{max}\) 的\(x_u,x_v\)
最后答案加上 \(\sum_{u}^{v}(x)\) 即可,复杂度大约在 \(O(n\log n)\) 左右