AtCoder Regular Contest 125 - ARC125
B - Squares
题意
给出一个 ,求有多少对 满足如下条件:
-
。
-
是一个平方数。(规定 也是平方数)
答案对 取模。
数据范围:
思路
设 ,则
令 ,则:
可以发现, 的取值一共只有 种。
对于每一个 只用 求出 即可。
不难发现, 的取值只能为 ,
令 ,故一共有 种取值。
总复杂度 。
点击显/隐代码
#include <bits/stdc++.h>
#define db double
#define ll long long
#define int ll
#define vi vector<int>
#define vii vector<vi >
#define pii pair<int, int>
#define vp vector<pii >
#define vip vector<vp >
#define mkp make_pair
#define pb push_back
#define Case(x) cout << "Case #" << x << ": "
using namespace std;
const int INF = 0x3f3f3f3f;
const int P = 998244353;
signed main(){
#ifdef _DEBUG
// FILE *file = freopen("out", "w", stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
int n, ans = 0;
cin >> n;
for (int i = 1; i * i <= n; i++) {
ans = (ans + 1 + (min(n/i, 2*n-i) - i) / 2) % P;
}
cout << ans << '\n';
return 0;
}
C - LIS to Original Sequence
题意
给出 和一个长度为 的序列 ,求一个 的排列,使得序列 是该排列的一个最长上升子序列(LIS - longest increasing subsequence),并且要求排列的字典序最小。
输入保证 是一个严格单增序列。
数据范围:
思路
考虑如何通过 来构造出一个排列 ,用 代表排列 中的第 个元素:
首先,当 时,。
其次,当 时:
-
如果 ,那么一定有 ,才能使得 的字典序最小,且一定能满足要求。
-
如果 ,那么一定有 ,那么此时 中的数字1还没有使用过,如果我们令 是不影响LIS的,因为题目只要求是LIS中一个即可,而且这样能使得字典序保持最小,所以有 。
- 证明:。反设:若 ,那么最长上升子序列一定会比 多出一个元素,不满足题意;若 ,则不满足字典序最小这个条件,综上,。
上面都只考虑了 ,由于这个操作具有独立性,可以直接将 删去,考虑后面的元素,每个元素都按照上述方式加入排列 中,只不过元素 的定义向右移了几位。
可以使用双指针模拟, 指向 中元素, 指向 中当前的 “1”(也就是当前能插入的最小的数字),保证不重复插入即可,如果枚举到了最后一个元素,按照 的情况处理即可。
总复杂度 。
点击显/隐代码
#include <bits/stdc++.h>
#define db double
#define ll long long
#define int ll
#define vi vector<int>
#define vii vector<vi >
#define pii pair<int, int>
#define vp vector<pii >
#define vip vector<vp >
#define mkp make_pair
#define pb push_back
#define Case(x) cout << "Case #" << x << ": "
using namespace std;
const int INF = 0x3f3f3f3f;
const int P = 998244353;
const int N = 2e5 + 10;
int vis[N];
signed main(){
#ifdef _DEBUG
// FILE *file = freopen("out", "w", stdout);
#endif
int n, m;
scanf("%lld %lld", &n, &m);
vi ans;
for (int i = 0, p = 1; i < m; i++) {
int x;
scanf("%lld", &x);
if (i == m-1) {
for (int j = n; j >= p; j--) {
if (!vis[j]) {
ans.pb(j);
}
}
break;
}
ans.pb(x);
if (x != p) {
vis[x] = 1;
ans.pb(p);
}
while (vis[++p]);
}
for (auto i : ans) cout << i << ' ';
return 0;
}
AtCoder Regular Contest 125 - ARC125
https://wty-yy.github.io/posts/57678/