Codeforces Round #752 (Div. 2) ABCDE题解
比赛地址Codeforces Round #752 (Div. 2)
很容易看出,如果对第 个执行插入操作,那么对 个都会影响到,所以只需要找出偏移量最大的就行了
#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}
inline void solve() {
int n; cin >> n;
int res = 0;
for (int i = 1; i <= n; i ++ ) {
int x; cin >> x;
if (x <= i) continue;
res = max(x - i, res);
}
cout << res << endl;
}
int main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
auto now = clock();
#endif
ios::sync_with_stdio(false), cin.tie(nullptr);
cout << fixed << setprecision(2);
int T; cin >> T;
while (T -- )
solve();
#ifdef DEBUG
cout << "============================" << endl;
cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
return 0;
}
奇偶分类讨论
假如是偶数的话,直接构造 个 即可。
受到启发,如果是奇数的话,直接构造 个 即可,故只要存在 就可以构造出来,否则就构造不出来。
#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}
inline void solve() {
int n; cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> a[i];
if (n & 1) {
for (int i = 1; i < n; i ++ ) {
if (a[i] >= a[i + 1]) {
cout << "YES" << endl;
return ;
}
}
cout << "NO" << endl;
} else cout << "YES" << endl;
}
int main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
auto now = clock();
#endif
ios::sync_with_stdio(false), cin.tie(nullptr);
cout << fixed << setprecision(2);
int T; cin >> T;
while (T -- )
solve();
#ifdef DEBUG
cout << "============================" << endl;
cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
return 0;
}
对着题意硬模拟就行,是不会T的,主要是 故暴力也不会T。
#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}
inline void solve() {
int n; cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> a[i];
for (int i = 1; i <= n; i ++ ) {
if (a[i] % (i + 1) == 0) {
int j = i;
while (j > 1 && a[i] % (j + 1) == 0) j --;
if (a[i] % (j + 1) == 0) {cout << "NO" << endl; return ;}
}
}
cout << "YES" << endl;
}
int main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
auto now = clock();
#endif
ios::sync_with_stdio(false), cin.tie(nullptr);
cout << fixed << setprecision(2);
int T; cin >> T;
while (T -- )
solve();
#ifdef DEBUG
cout << "============================" << endl;
cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
return 0;
}
构造题,也是分类讨论
首先容易看出,当 的时候,直接输出 即可
否则我们当 的时候,输出 ,因为
最后一种是比较难想的,当 的时候
最初的想法是找到一个 到 之间的数,使得其满足,最初的想法是 ,但是当 比 大好多的时候就不对了,所以尝试加一个系数。最终凑出了 。
因为
#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}
inline void solve() {
LL x, y; cin >> x >> y;
if (y % x == 0) cout << x << endl;
else {
if (y < x) cout << x + y << endl;
else cout << y / 2 + y / x * x / 2 << endl;
}
}
int main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
auto now = clock();
#endif
ios::sync_with_stdio(false), cin.tie(nullptr);
cout << fixed << setprecision(2);
int T; cin >> T;
while (T -- )
solve();
#ifdef DEBUG
cout << "============================" << endl;
cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
return 0;
}
考点:dp
若数组本身为非递减,则操作次数为0,否则一定存在 ,从这个入手。
设 ,其中
容易得出,,考虑到对前面数组的影响,故 越大越好,所以当 时, 最大为 ,同时操作次数也最少为
根据这个贪心,我们可以写出 的一个算法,但是显然复杂度过高,需要优化。
状态设计, 表示以 开头的,经过数字拆分后以 开头子序列个数之和。
容易得到
注意到,这个转移的有效次数只有 次,也就是 的个数是 级别的(类似数论分块)
所以实际上的复杂度是 级别的。
转移的同时统计答案,为
由于 的空间存不下,而且每次转移只用到上一层的,所以考虑滚动数组
#include <bits/stdc++.h>
#define endl '\n'
#define ls u << 1
#define rs u << 1 | 1
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL,LL> PLL;
const int INF = 0x3f3f3f3f, N = 1e5 + 10;
const int MOD = 998244353;
const double eps = 1e-6;
const double PI = acos(-1);
inline int lowbit(int x) {return x & (-x);}
LL dp[2][N];
inline void solve() {
int n; cin >> n;
vector<int> a(n + 1);
int mx = 0;
for (int i = 1; i <= n; i ++ ) cin >> a[i], mx = max(mx, a[i]);
for (int i = 0; i <= mx; i ++ ) dp[0][i] = dp[1][i] = 0;
vector<int> v[2];//存上一层有效转移过来的x
LL res = 0;
for (int i = n; i; i -- ) {
int p = i & 1;
v[p].push_back(a[i]);
dp[p][a[i]] = 1;
int last = a[i];
for (auto x : v[p ^ 1]) {
int k = (a[i] + x - 1) / x;
int j = a[i] / k;
res = (res + (k - 1) * dp[p ^ 1][x] % MOD * i % MOD) % MOD;
dp[p][j] = (dp[p][j] + dp[p ^ 1][x]) % MOD;
if (last == j) continue;
v[p].push_back(j), last = j;
}
for (auto x : v[p ^ 1]) dp[p ^ 1][x] = 0;//一定要重置,否则就不是“滚动”的了
v[p ^ 1].clear();
}
cout << res << endl;
}
int main() {
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
auto now = clock();
#endif
ios::sync_with_stdio(false), cin.tie(nullptr);
cout << fixed << setprecision(2);
int T; cin >> T;
while (T -- )
solve();
#ifdef DEBUG
cout << "============================" << endl;
cout << "Program run for " << (clock() - now) / (double)CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif
return 0;
}