2024.12.28~2025.12.28 杂题选做
ABC400E
首先,我们设 \(p,q\) 为两个质数,那么 \(a=p^{2m}q^{2n}\) 是 \(a\) 是 \(400\) 数的充分必要条件。
考虑枚举出 \(p^{2m}\),先跑质数筛。随后两两配对,大于 \(10^{12}\) 或溢出就 break,把这些数放入 vector,查询时二分即可,这样做 500ms 可以过。
优化思路
赛时没有想出来。
通过初一数学可得,\(p^{2m}q^{2n}=(p^mq^n)^2\)。
因此我们枚举 \(p^m\) 和 \(q^n\),保证其不超过 \(\sqrt{10^{12}}=10^6\)。最后放入平方即可。
P8933
本文作者:\(\color{red}\text{DoubleQLzn}\color{green}✓\)
题目:洛谷 P8933 [JRSKJ R7] 技巧性的块速递推 - 题目传送门
难度:\(\color{green}\tt 普及+\)
\(\text{Knowledge}\)
- 【\(5\)】深度优先搜索
\(\text{Solution}\)
观察题目,考虑特殊性质。
思考四个数 \((a,b,c,d)\) 什么时候满足条件。
首先,当后面的条件满足时,前面一定满足。
因此考虑后面的条件,只有当 \(2\) 黑 \(2\) 白时满足。知道前 \(3\) 个就可以推出第 \(4\) 个。
所以,填的颜色具有周期性,\(2\) 个周期后方案确定,因此 \(n>5,m>5\) 的答案是 \(n=5,m=5\),预处理答案,这部分深度优先搜索即可。
\(\text{Code}\)
#include <bits/stdc++.h>
using namespace std;
#define int long long
int ans[12][12],a[12][12],m,n;
int same(int a,int b,int c)
{
if (a == b && b == c) return 1;
else return 0;
}
int s2(int a,int b,int c,int d)
{
unordered_map<int,int> f2;
f2[a]++,f2[b]++,f2[c]++,f2[d]++;
if (f2[1] == 3 || f2[0] == 3) return 1;
else return 0;
}
bool check()
{
for (int i = 1;i <= m;i++)
{
for (int j = 1;j <= n;j++)
{
if (i + 2 <= m && same(a[i][j],a[i + 1][j],a[i + 2][j])) return 0;
if (j + 2 <= n && same(a[i][j],a[i][j + 1],a[i][j + 2])) return 0;
if (i + 2 <= m && j + 2 <= n && same(a[i][j],a[i + 1][j + 1],a[i + 2][j + 2])) return 0;
if (i + 2 <= m && j - 2 >= 1 && same(a[i][j],a[i + 1][j - 1],a[i + 2][j - 2])) return 0;
}
}
for (int i = 1;i <= m;i++)
{
for (int j = 1;j <= n;j++)
{
if (i + 3 <= m && s2(a[i][j],a[i + 1][j],a[i + 2][j],a[i + 3][j])) return 0;
if (j + 3 <= n && s2(a[i][j],a[i][j + 1],a[i][j + 2],a[i][j + 3])) return 0;
if (i + 3 <= m && j + 3 <= n && s2(a[i][j],a[i + 1][j + 1],a[i + 2][j + 2],a[i + 3][j + 3])) return 0;
if (i + 3 <= m && j - 3 >= 1 && s2(a[i][j],a[i + 1][j - 1],a[i + 2][j - 2],a[i + 3][j + 3])) return 0;
}
}
return 1;
}
int s = 0;
void dfs(int x,int y)
{
if (y > n) y= 1,x++;
if (x > m)
{
if (check())
{
ans[m][n] = (ans[m][n] + 1) % 998244353;
}
return ;
}
a[x][y] = 1;
dfs(x,y + 1);
a[x][y] = 0;
dfs(x,y + 1);
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
memset(a,-1,sizeof a);
for (int i = 1;i <= 5;i++)
{
for (int j =1;j <= 5;j++)
{
memset(a,-1,sizeof a);
m = i,n = j;
dfs(1,1);
}
}
int T,x,y;
cin >> T;
while (T--)
{
cin >> x >> y;
cout << ans[min(x,5ll)][min(y,5ll)] << '\n';
}
return 0;
}
ABC391E
首先观察每个区间的答案,将其分为 \(3\) 个子区间 \(a,b,c\),定义一个区间的值为其的 \(A^{'}\)有 \(2\) 种情况:
- \(a,b,c\) 的值相等:最小花费为 \(a,b,c\) 的花费中前两小的和;
- \(a,b,c\) 的值不等:最小花费为原本值相等的两个子区间中花费的最小值。
由于每次都分成三个区间,具有递归特性,使用递归实现即可。
Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
int a[4000005];
int solve(int a,int b,int c)
{
int f[4] = {0};
f[a]++,f[b]++,f[c]++;
if (f[0] > f[1]) return 0;
else return 1;
}
int qsort1(int a,int b,int c)
{
vector<int> d;
d.push_back(a),d.push_back(b),d.push_back(c);
sort(d.begin(),d.end());
return d[0] + d[1];
}
int now=0;
pair<int,int> dfs(int l,int r)
{
now++;
//if (l > r) return make_pair(0,0);
//cout<<l<<' '<<r<<endl;
if (l == r) return make_pair(a[l],1);
else
{
// 1 3 2 2 3 3
int l1 = l,r1 = l1 + (r - l + 1) / 3 - 1;
int l2 = r1 + 1,r2 = r1 + ((r - l + 1) / 3);
int l3 = r2 + 1,r3 = r;
// cout<<l1<<' '<<l2<<' '<<l3<<' '<<r1<<' '<<r2<<' '<<r3<<' ';
pair<int,int> a = dfs(l1,r1);
pair<int,int> b = dfs(l2,r2);
pair<int,int> c = dfs(l3,r3);
int ans1 = solve(a.first,b.first,c.first);
int ans2;
if (a.first == b.first && b.first == c.first) ans2 = qsort1(a.second,b.second,c.second);
else
{
if (a.first == b.first) ans2 = min({a.second,b.second});
if (a.first == c.first) ans2 = min({a.second,c.second});
if (b.first == c.first) ans2 = min({b.second,c.second});
}
return make_pair(ans1,ans2);
}
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
int n;
cin >> n;
int len = 1;
for (int i = 1;i <= n;i++) len *= 3;
for (int i = 1;i <= len;i++)
{
char c;
cin >> c;
a[i] = c - 48;
}
cout << dfs(1,len).second;
return 0;
}
P11229
分类讨论简单题。
我们先求出每个数字需要的火柴数量。
| 数字 | 需要火柴数量 |
| :--------: | :-------: |
| $0$ | $6$ |
| $1$ | $2$ |
| $2$ | $5$ |
| $3$ | $5$ |
| $4$ | $4$ |
| $5$ | $5$ |
| $6$ | $6$ |
| $7$ | $3$ |
| $8$ | $7$ |
| $9$ | $6$ |
想要让数字最小,首先就要让 **位数** 最小,很明显,**要尽可能地多使用 $\bold{8}$**。
知道整体策略后,我们可以找一下规律,从数据范围不难看出,答案和 $7$ 与取模有关,继续找规律。
| 数字与取余值 | 结果 |
| :-------: | :---------: |
| $28 \bmod 7=0$ | $8888$ |
| $29 \bmod 7=1$ | $10888$
| $30 \bmod 7=2$ | $18888$ |
| $31 \bmod 7=3$ | $20088$ |
| $32 \bmod 7=4$ | $20888$ |
| $33 \bmod 7=5$ | $28888$ |
| $34 \bmod 7=6$ | $68888$ |
很容易发现,对于每个数字 $x$,结尾均有 $\lfloor{x\div 7}\rfloor-2$ 个 $8$,前面则各不相同,这也是结论。
同时,不要忘了小数据打表,要打表到 $14$。
综上,可以 AC 本题。
### 考场代码 ($0$ 分)
开的 `string a[100005]`。
MLE。
### AC 代码
```cpp
#include <bits/stdc++.h>
using namespace std;
string f[100005] = {"-1","-1","1","7","4","2","6","8","10","18","22","20","28","68","88","108","188","200","208","288","688","888","1088","1888","2008","2888","6888","8888","10888"};
int main()
{
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
if (n <= 14) cout << f[n] << endl;
else
{
int k = n / 7 - 1;
string b;
for (int i = 1;i < k;i++) b.push_back('8');
if (n % 7 == 0) cout << "88" << b;
if (n % 7 == 1) cout << "108" << b;
if (n % 7 == 2) cout << "188" << b;
if (n % 7 == 3) cout << "200" << b;
if (n % 7 == 4) cout << "208" << b;
if (n % 7 == 5) cout << "288" << b;
if (n % 7 == 6) cout << "688" << b;
cout << '\n';
}
}
return 0;
}
CF2044E
我们可以求出 $k$ 的所有非负整数次幂 $x_1,x_2,\cdots,x_{log_k{10^9}}$。然后枚举所有满足要求的数,对于任意 $x_i$,如果 $a$ 满足要求,应该满足下面四个不等式:
- $x_ia\geq l2$
- $x_ia\leq r2$
- $a\geq l_1$
- $a\leq r_2$
不妨移项,$a\geq l2\div a$,$a\leq r2\div a$,前者上取整,后者下取整,就是前两个不等式的解集。
最后求两个解集的交叉部分即可。
### Code
```cpp
#include <bits/stdc++.h>
using namespace std;
#define int long long
int t,k,l1,r1,l2,r2;
int jiaocha(int l1,int r1,int l2,int r2)
{
int s = min(r1,r2) - max(l1,l2) + 1;
return max(0ll,s);
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> t;
while (t--)
{
cin >> k >> l1 >> r1 >> l2 >> r2;
vector<int> g;
int now = 1;
while (now <= 1000000000)
{
g.push_back(now);
now = now * k;
}
int ans = 0;
for (auto a : g)
{
int down = ceil(l2 * 1.0 / a),up = r2 / a;
ans = ans + jiaocha(down,up,l1,r1);
}
cout << ans << '\n';
}
return 0;
}

浙公网安备 33010602011771号