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 << ' ';//如果出现过,就填d
st[d]++;
}
else {
cout << a << ' ';没有出现过,就填a
st[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)\) 左右
标签:cout,int,cin,long,CF,补题,tie,streampreset,Div.4 From: https://www.cnblogs.com/dianman/p/18622435