CSP模拟3
A. 回文
\(20\) 多分的纯暴力搜索,\(A_{i,j} = A_{i-1,j+1}\) 可以判完回文直接递推出路径数,共 \(42 \text{pts}\)。
正解 \(DP\)。
回文可以转化一下思路,两个人分别从 \((1,1),(n,m)\) 出发,走的路径相同的方案数。
设计 \(dp[i][j][s][t]\) 为第一个人在 \((i,j)\) 位置,第二个人在 \((s,t)\) 位置的方案数。
转移要注意步数相同,即 \(i + j - 2 = n + m - s - t\)。
因为我们每走一步会使你的坐标 \(x + y\) 加上 \(1\),又因为我们坐标都是从 \(1\) 开始的,所以第一个人路径长度就是 \(x + y - 2\)。
第二个人由于是从 \(n + m\) 开始,不太一样。
所以就可以压掉一维,\(t = n + m + 2 - s - i - j\)(好长)。
最后要考虑一下回文有两种情况,一种是长度为奇数,即最后两个人走到同一个位置;另一种长度为偶数,即二者相邻的状态,这种要考虑两种相邻的情况(上下和左右)。
这个思路来自sandom学长的博客,稍微解释地详细了一下。
这道题最坑的就是模数 \(993244853\)!!!!!!
Code
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
const int N = 505;
const int Mod = 993244853;
int n,m;
char a[N][N];
int dp[N][N][N];
long long ans;
int main() {
ios::sync_with_stdio(false);
cin >> n >> m;
for(int i = 1;i <= n; i++)
for(int j = 1;j <= m; j++)
cin >> a[i][j];
if(a[1][1] == a[n][m])
dp[1][1][n] = 1;
else {
cout << "0";
return 0;
}
for(int i = 1;i <= n; i++) {
for(int j = 1;j <= m; j++) {
for(int s = n;s >= 1; s--) {
int t = n + m + 2 - i - j - s;
if(t < 1 || t > m)
continue;
ans = dp[i][j][s];
if(a[i][j] == a[s][t])
ans = ans + dp[i - 1][j][s + 1] + dp[i - 1][j][s] + dp[i][j - 1][s + 1] + dp[i][j - 1][s];
dp[i][j][s] = ans % Mod;
}
}
}
ans = 0;
for(int i = 1;i <= n; i++) {
for(int j = 1;j <= m; j++) {
int s,t;
s = i,t = j;
if(i + j + s + t == n + m + 2)
ans += dp[i][j][s];
s = i + 1,t = j;
if(i + j + s + t == n + m + 2)
ans += dp[i][j][s];
s = i,t = j + 1;
if(i + j + s + t == n + m + 2)
ans += dp[i][j][s];
ans %= Mod;
}
}
cout << ans;
return 0;
}
B. 快速排序
指针看不懂寄
简单看一下题目里给的快速排序。
\(\text{namespace\_std}\) 的快排是以待排区间的第一个数为基准值的,把小于基准值的放在基准值左边,其余的放在基准值右边。
而 \(nan\) 无论与任何数比较都会返回 \(0\)。
所以对于操作序列。
若第一个数是 \(nan\),这次操作不会改变任何一个数的位置;
若第一个数不是 \(nan\),把它后边小于它的数都放在它前面。
Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 114514 * 5;
int T,n;
int a[N];
string st;
int To_int(string s) {
int ans = 0;
int bit = 1;
for(int i = s.size() - 1;i >= 0; i--) {
ans += (s[i] - 48) * bit;
bit *= 10;
}
return ans;
}
deque<int> b;
priority_queue< int,vector<int>,greater<int> > q;
int max_num;
void qsort(int l,int r) {
if(l >= r) {
b.push_back(a[l]);
return ;
}
if(!a[l])
b.push_back(0);
else if(a[l] >= max_num) {
while(!q.empty() && q.top() < a[l]) {
b.push_back(q.top());
q.pop();
}
b.push_back(q.top());
q.pop();
max_num = a[l];
}
qsort(l + 1,r);
return ;
}
signed main() {
ios::sync_with_stdio(false);
cin >> T;
while(T--) {
cin >> n;
for(int i = 1;i <= n; i++) {
cin >> st;
if(st[0] != 'n')
a[i] = To_int(st);
else
a[i] = 0;
}
for(int i = 1;i <= n; i++)
if(a[i])
q.push(a[i]);
qsort(1,n);
for(int i = 0;i < n; i++)
if(b[i] != 0)
cout << b[i] << " ";
else
cout << "nan ";
cout << "\n";
while(!q.empty())
q.pop();
while(!b.empty())
b.pop_back();
max_num = 0;
}
return 0;
}