题目链接:AtCoder Beginner Contest 363
总结:前三题过于easy了,C的暴力写挂了一发。D差一点?,差一点总结;
A. Piling Up
fag:签到
B. Japanese Cursed Doll
fag: 签到
Solution:排序后求第 p p p个数的值与 t t t的差即可。
C. Japanese Cursed Doll
fag:模拟
Solution:暴力模拟即可
void solve(){
cin >> n >> k;
string s;
cin >> s;
int ans = 0;
sort(s.begin(), s.end());
do {
bool fllag = true;
for (int i = 0; i + k - 1 < n; i ++){
bool flag = true;
for (int tt = i, t = i + k - 1; tt <= t; tt ++ , t --){ // 判断每一个回文
if (s[tt] != s[t]){ // 不是回文
flag = false;
break;
}
}
if (flag){
fllag = false;
break;
}
}
if (fllag)
ans ++;
}while (next_permutation(s.begin(), s.end()));
cout << ans;
}
D.Palindromic Number
fag:思维?打表?
Description:求第 n n n个回文数,不含前导零。 1 < = n < = 1 e 18 1 <= n <= 1e18 1<=n<=1e18
Solution:考虑构造一个长度为 n n n的回文数,显然对于偶数为只需要构造前一半就行,奇数位多了最中间的一位。
- 显然我们不能直接求出第 n n n个回文数,但是能够求出第 n n n个回文数的长度,知道长度之后就能求这个长度对应的第几个回文数。
- 打表或者模拟发现:奇数位的个数是上一位 * 10, 偶数位的个数等于上一位;如 1111 = > 11 ( 0 , 1 , . . . 9 ) 11 1111 => 11(0, 1, ...9)11 1111=>11(0,1,...9)11中间可以填 10 10 10个数,但是 12321 = > 123321 12321 => 123321 12321=>123321只能将中间的数复制一下
1: 10
2: 9
3: 90
4: 90
5: 900
- 然后我们一位一位找第 n n n个回文数的长度,得到长度之后构造就行。
Competing:构造的时候细节出错了。
void solve(){
int x;
cin >> x;
if (x <= 10){
cout << x - 1 << endl;
return;
}
/*
枚举答案的位数:
2: 9
3: 90
4: 90
5: 900
*/
int res = 9;
LL ans = 10; // 之前的和
for (int i = 2; ; i ++){
if (i & 1){ // 奇数乘10
res = res * 10;
}
if (x - ans <= res){ // 避免ans + res 爆longlong
x -= ans; // 当前位数的第几个数
if (i & 1){
i /= 2;
int t = (x + 9) / 10; // 前缀是多少
int tt = ((x - 1) % 10 + 10) % 10; // 奇数位是几
// debug(x, t, tt);
t = qmi(10, i - 1) + t - 1;
string s = to_string(t);
cout << s;
cout << tt;
reverse(s.begin(), s.end());
cout << s;
cout << endl;
return;
}
else{ // 偶数从100 ~ 999
i /= 2;
int t = qmi(10, i - 1) + x - 1;
string s = to_string(t);
cout << s;
reverse(s.begin(), s.end());
cout << s;
cout << endl;
return;
}
}
ans += res;
}
}
E. Sinking Land
fag:优先队列 + bfs
Description:有一个 n ∗ m n * m n∗m的小岛,每个小岛的高度为 a i j a_{ij} aij。每天海水的高度 + 1 +1 +1(初始为 0 0 0),当小岛的高度小于等于海水的高度时并且四个方向有相邻的海水时,小岛会被淹没变为海水,求每天未被淹没的海水。
Solution:显然我们是需要bfs的,然后我们使用优先队列存储。队头的元素小于海水高度时就直接出队。
Competing:写bfs出队时,猜设置访问状态st,应该先设置状态st,再入队,否则会有许多重复的点入队
void solve(){
cin >> n >> m >> k;
vector a(n + 5, vector<int>(m + 5));
vector st(n + 5, vector<int>(m + 5));
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
cin >> a[i][j];
priority_queue<pair<int, pii>, vector<pair<int, pii>>, greater<pair<int, pii>>> qu;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++){
if (i == 1 || i == n || j == 1 || j == m)
{
qu.push({a[i][j], {i, j}});
st[i][j] = true;
}
}
int res = n * m;
for (int i = 1; i <= k; i ++){
while (qu.size() && qu.top().fi <= i){
auto [t, tt] = qu.top();
qu.pop();
auto [x, y] = tt;
res --;
for (int j = 0; j < 4; j ++){
int dx = x + dir[j][0], dy = y + dir[j][1];
if (dx < 1 || dx > n || dy < 1 || dy > m || st[dx][dy])
continue;
st[dx][dy] = true;
qu.push({a[dx][dy], {dx, dy}});
}
}
cout << res << endl;
}
}
F. Palindromic Expression
fag:递归 +构造
Description:用 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , ∗ 1, 2, 3, 4, 5, 6 ,7, 8, 9, * 1,2,3,4,5,6,7,8,9,∗构造一个回文串,满足以字母开头并且表达式的值为 n n n,求该回文串,不存在输入 − 1 -1 −1。
1 < = n < = 1 e 12 1 <= n <= 1e12 1<=n<=1e12
Solution:先考虑给定的值就是一个回文串并且里面不含 0 0 0那么直接输出。
-
首先枚举 n n n的因数,如果
n mod x == 0
并且 x x x中不含 0 0 0且 x x x是回文数; y y y是 x x x的回文数,且n / x mod y == 0
,那么我们只需要考虑 n / x / y n / x / y n/x/y,如果构造就行。 -
因此我们定义一个函数 f f f:如果 x x x是回文串并且里面不含 0 0 0那么直接返回。
-
否则枚举它的因数,当因数 x x x满足上面说所的条件,递归到 f ( n / x / y ) f(n / x / y) f(n/x/y)。
Competing:忘记考虑因数中也不能含 0 0 0了。
int reverse(int x){ // 返回x的回文数
string t = to_string(x);
reverse(t.begin(), t.end());
int y = stol(t);
return y;
}
bool is_Hui(int x){ // 判断x是否是回文数
string s = to_string(x);
for (int i = 0, j = s.size() - 1; i <= j; i ++, j --){
if (s[i] != s[j] || s[i] == '0')
return false;
}
return true;
}
string f(int x){
string s = to_string(x);
if (is_Hui(x)) // 如果x是回文数,并且不含0之间返回
return s;
for (int i = sqrt(x) + 1; i >= 2; i --){ // 枚举x的质因数
if (x % i == 0 && to_string(i).find('0') == -1){
int y = reverse(i); // i的回文数
if ((x / i) % y == 0){
string t = f(x / i / y);
if (t != "0"){
return to_string(i) + "*" + t + "*" + to_string(y);
}
}
}
}
return "0";
}
void solve(){
int n;
cin >> n;
string ans = f(n);
if (ans == "0" || ans.size() > 1000)
cout << -1 << endl;
else
cout << ans << endl;
}