Contestant. Rank 1886. Rating -17.
A. Prefix and Suffix Array
题意
给定一个字符串的所有前缀和后缀,如
思路
既然是前后缀,并且回文字符串的判断只需比较
时间复杂度:
对应AC代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
const int N = 2e5 + 10, inf = 0x3f3f3f3f3f3f3f3f, mod = 998244353;
void solve(){
int n;
cin >> n;
vector<string> s;
for(int i=0;i<2 * (n - 1); i++){
string now;
cin >> now;
if(now.size() == n / 2) s.emplace_back(now);
}
std::reverse(s[0].begin(), s[0].end());
cout << (s[0] == s[1] ? "YES\n" : "NO\n");
}
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while(t --) solve();
}
真是阴间时间下猪脑转不动了(
B. Not Dividing
题意
给定一个长度为
思路
首先,不能出现
其次,奇数不能被偶数整除,而偶数可以被奇数整除,但该偶数
最后,我们得到下面的结论:遇到整除,将后者加一,除非遇到
时间复杂度:
对应AC代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
const int N = 2e5 + 10, inf = 0x3f3f3f3f3f3f3f3f, mod = 998244353;
void solve(){
int n;
cin >> n;
int pre;
cin >> pre;
if(pre == 1) pre ++;
cout << pre << ' ';
for(int i=1;i<n;i++){
int cur;
cin >> cur;
if(cur == 1) cur ++;
if(cur % pre == 0){
pre = cur + 1;
}else pre = cur;
cout << pre << ' ';
}
cout << '\n';
}
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while(t --) solve();
}
当然不是简简单单的判奇偶啊…
C. Scoring Subsequences
题意
定义一个不递减序列
思路
首先,第一个数对应的答案一定是
那么,遍历到第二个数的时候,我们可以继续保持答案
那么,假设我们选了两个数,那么继续遍历到第三个数的时候,由于第二三两个数的乘积大于等于前两个数的乘积,所以答案是肯定大于等于
为什么不用再往前考虑呢?因为之前我们已经判断过了,比如说第二次只选了一个数,那么
因此,这道题就变得很好写了(
时间复杂度:
对应AC代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
const int N = 2e5 + 10, inf = 0x3f3f3f3f3f3f3f3f, mod = 998244353;
int a[N];
void solve(){
int n;
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
vector<int> ans(n + 1);
ans[1] = 1;
for(int i=2;i<=n;i++){
ans[i] = ans[i - 1];
if(a[i - ans[i]] > ans[i]) ans[i] ++;
}
for(int i=1;i<=n;i++) cout << ans[i] << ' ';
cout << '\n';
}
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
while(t --) solve();
}
想个半天,差点没看到给的序列不递减,淦
D. Counting Factorizations
题意
对于一个数
现在,给定上述序列,长度为
思路
特判
首先,底数一定为不同的
指数的全排列问题
否则,我们假设已经选好了
这是一个含有重复数字的全排列问题,它有一个公式,套用在本题即为下面的称述:
我们定义
为所有合数的数量的序列,遍历得到长度为 ,如 中, ; 同理,
为所有质数的数量的序列,长度为 ; 考虑到有部分质数被拿走,作为了底数,所以部分
会减少一定的值。因为底数不能重复,所以最多减少 ,我们定义 为所有质数扣去底数后的数量的序列;
那么,最后的答案即为所有
简化问题
显然,
因此,我们只需要在所有不同质数中挑选
当然,我们可以递归枚举,但是这样复杂度未免太高了。
如何递推
所有乘积的式子的元素顺序是不影响答案的,所以我们不妨按照序列的顺序将每个式子的元素排序。
如对于下面的序列,我们希望从这
1 2 3 5 4
因为我们确定了元素的顺序,所以我们不妨来考虑一个特定的元素:
对于一个乘积式子
也就是
也就是说,前面两项的选择只和
我们还可以将上面的式子提取一下:
这时,
而对于类似于
事实上,我们可以加上含
显然,我们还需要加上不选这个数字的情况,也就是前一个数字的前
因而,上述思路可以用二维
关于
其中,
优化复杂度
阶乘和阶乘逆元可以预处理得到,而质数的判断可以使用线性筛(欧拉筛),求逆元的话可以线性递推也可以快速幂。
时间复杂度:常数有点大的
对应AC代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int, int>
const int N = 1e6 + 10, inf = 0x3f3f3f3f3f3f3f3f, mod = 998244353;
bool vis[N], is[N];
int pri[N], cnt;
int fact[N], fact_inv[N];
int qp(int a, int b){
int ans = 1;
while(b > 0){
if(b & 1) ans = ((ans % mod) * (a % mod)) % mod;
a = ((a % mod) * (a % mod)) % mod;
b >>= 1;
}
return ans;
}
void init() {
for (int i = 2; i <= 1e6; ++i) {
if (!vis[i]) {
pri[cnt++] = i;
is[i] = true;
}
for (int j = 0; j < cnt; ++j) {
if (1ll * i * pri[j] > 1e6) break;
vis[i * pri[j]] = true;
if (i % pri[j] == 0) break;
}
}
fact[0] = fact_inv[0] = 1;
for(int i=1;i<=1e6;i++){
fact[i] = ((fact[i - 1] % mod) * (i % mod)) % mod;
fact_inv[i] = qp(fact[i], mod - 2);
}
}
void solve() {
int n;
cin >> n;
vector<int> in(2 * n);
map<int, int> tot;
for (int i = 0; i < 2 * n; i++) {
cin >> in[i];
tot[in[i]]++;
}
vector<int> c;
int el = fact[n];
for(auto e : tot){
if (is[e.first]) c.emplace_back(e.second);
el = ((el % mod) * (fact_inv[e.second] % mod)) % mod;
}
if (c.size() < n) {
cout << 0 << '\n';
return;
}
vector<vector<int>> dp(c.size() + 1, vector<int>(n + 1, 0));
dp[0][0] = 1;
for (int i = 1; i <= c.size(); i++) {
for (int j = 0; j <= n; j++) {
dp[i][j] = dp[i - 1][j];
if (j > 0) dp[i][j] = (dp[i][j] + dp[i - 1][j - 1] * c[i - 1]) % mod; //这里的c初始下标是0
}
}
cout << (el * dp[c.size()][n]) % mod << '\n';
}
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
init();
int t = 1;
//cin >> t;
while(t --) solve();
}
我人似了
- 本文链接 https://floating-ocean.github.io/blog_old/posts/4284380403/
- 版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!