【真题研究】春季测试 2023
T1.涂色游戏(paint)
可以按照题意模拟,每一次暴力对于每一行列染色,时间复杂度 \(O(qn)\)。可得60pts。
因为颜色可以覆盖,某一格的颜色往往取决于最后一次被染到的颜色。
于是我们采用打标记的方式。每一次染色(行或列)就在当前行列打标记,记操作时间戳 \(t\)。
最后输出答案时枚举每一格,比较当前行列的时间戳 \(t\),\(t\) 更大的标记对应的颜色就是覆盖的颜色。
时间复杂度 \(O(q+nm)\),100pts。
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define rint register int
#define For(i,l,r) for(rint i=l;i<=r;++i)
#define FOR(i,r,l) for(rint i=r;i>=l;--i)
using namespace std;
inline int read() {
rint x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N = 1e6 + 5;
struct Node {
int id, c;
} Ansh[N], Ansl[N];
int n, m, T, q;
void init() {
For(i,1,n) {
For(j,1,m) {
Ansh[i] = (Node) {0, 0};
Ansl[j] = (Node) {0, 0};
}
}
}
signed main() {
T = read();
while(T--) {
n = read(), m = read(), q = read();
init();
For(l,1,q) {
int op = read(), x = read(), c = read();
if(op == 0) {
Ansh[x] = (Node) {l, c};
} else {
Ansl[x] = (Node) {l, c};
}
}
For(i,1,n) {
For(j,1,m) {
if(j != m) {
if(Ansh[i].id > Ansl[j].id) {
cout << Ansh[i].c << ' ';
} else {
cout << Ansl[j].c << ' ';
}
}
else {
if(Ansh[i].id > Ansl[j].id) {
cout << Ansh[i].c;
} else {
cout << Ansl[j].c;
}
}
}
cout << endl;
}
}
return 0;
}
T2.幂次(power)
- \(k=1\)
答案显然就是 \(n\)。
- \(k\geq 3\)
注意到,若 \(x\) 质因数分解后满足不为 \(p_1^{a}p_2^{a}p_3^{a}...p_m^{a}\) 的形式,则将答案在 \(x\) 时记下不会记重。
枚举底数 \(a\),时间复杂度显然在 \(O(n^{\frac{1}{3}})\) 阶内。然后暴力枚举指数 \(b\),并打标记防止记重(标记数组用 map 存)。统计记录下个数。
这样时间复杂度 \(O(n^{\frac{1}{3}}\log n)\),可以接受。45pts。
- \(k=2\)
相当于在 \(k\ge 3\) 的基础上多加了一堆完全平方数。
已知所有 \(\le n\) 的完全平方数的数量为 \(\left\lfloor \sqrt n \right\rfloor\)。但是直接加上会记重,原因是那些 \(k \ge 3\) 中的方案里也有完全平方数,比如 \(4^3=8^2=64\)。于是你只要记下那些 \(k \ge 3\) 中的方案的完全平方数的个数,容斥掉就可以了。
总时间复杂度还是 \(O(n^{\frac{1}{3}}\log n)\)。100pts。
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define rint register int
#define For(i,l,r) for(rint i=l;i<=r;++i)
#define FOR(i,r,l) for(rint i=r;i>=l;--i)
using namespace std;
int n, k, ans, und;
map<int, bool> vis;
int qpow(int a, int b) {
int res = 1;
for (; b; b >>= 1, a = a * a) {
if(b & 1) res = res * a;
}
return res;
}
signed main() {
cin >> n >> k;
if(k == 1) cout << n << '\n';
else if(k >= 2){
for (int i = 2; i * i * i <= n; ++i) {
for (int j = i * i, kk = 2; ; ) {
if(j > n/i) break;
j *= i, kk++;
if(kk < k) continue;
if(vis[j]) continue;
vis[j] = 1;
ans++;
if((int)sqrtl(j)*sqrtl(j) == j) und++;
}
}
if(k >= 3) cout << ans+1 << '\n';
else cout << (int)sqrtl(n) + ans - und << '\n';
}
return 0;
}