模拟赛题目复盘
ka_da_Duck · · 个人记录
难度: CSPS - NOIP
Day11
估分
T1.P11989 弱化
::::info[Description]
有
每个任务有完成限时
每一时刻,你可以选择一个任务
最小化
求序列的总和。
solution
首先一个数字最终的值一定是由它的因数推出来的。
设
用
找到
所以我们计算
::::info[代码]
#include <bits/stdc++.h>
#define pb push_back
#define pii pair<int, int>
#define int long long
using namespace std;
#ifdef ONLINE_JUDGE
#define debug(...) 0
#else
#define debug(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#endif
// you need fread or not?
const int maxn = 2e6 + 10;
int n, tot;
int p[maxn], mx[maxn], mn[maxn], ans[maxn];
bool vis[maxn];
void init() {
mx[1] = mn[1] = vis[1] = 1;
for (int i = 1; i < maxn; ++i)
ans[i] = 1;
for (int i = 2; i < maxn; ++i) {
if (!vis[i])
p[++tot] = mx[i] = mn[i] = i;
for (int j = 1; j <= tot && i * p[j] < maxn; ++j) {
vis[i * p[j]] = 1, mx[i * p[j]] = mx[i], mn[i * p[j]] = p[j];
if (i % p[j] == 0)
break;
}
}
for (int i = 2; i < maxn; ++i) {
ans[i] += 1 - mx[i];
for (int j = 2; i * j < maxn; ++j)
if (mx[i] <= mn[j])
ans[i * j] += 1 - mx[i];
}
for (int i = 1, o = 0; i < maxn; ++i, o = 0) {
for (int j = 2; i * j < maxn; ++j) {
ans[i * j] += o;
if (mx[i] <= mn[j])
ans[i * j] += j, o++;
}
}
for (int i = 1; i < maxn; ++i)
ans[i] += ans[i - 1];
}
void solve() {
cin >> n;
cout << ans[n] << '\n';
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
init();
int t;
cin >> t;
while (t--)
solve();
cout << flush;
return 0;
}
:::: Day10
Score
估 100 20 0 20
实 100 20 0 0
T1 abc166f 弱化
初始时 ABC 都有初值。
则式字变为
式子变为
设
则
推出
直接枚举
::::info[代码]
#include <bits/stdc++.h>
#define pb push_back
#define pii pair<int, int>
// #define int long long
using namespace std;
#ifdef ONLINE_JUDGE
#define debug(...) 0
#else
#define debug(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#endif
// you need fread or not?
int n, m, ans, sn, sm, a, b;
void solve() {
cin >> n >> m;
ans = 0;
sn = sqrt(n), sm = sqrt(m);
for (int i = 1; i <= sn; ++i) {
for (int j = 1; j <= sm; ++j) {
if (__gcd(i, j) != 1)
continue;
a = (i + j) * i, b = (i + j) * j;
if (a > n || b > m)
continue;
ans += min(n / a, m / b);
}
}
cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
cout << flush;
return 0;
}
::::
T2 arc104c
2.所有
3.若两线段有交集,则它们长度一样。
先给出所有
solution
首先特判,ababa..
考虑合法方案的形态,线段必然没有包含关系,考虑每个独立的段,发现必定形如:
前半部分是左端点,后半部分是右端点。
我们需要知道是否有合法方案,考虑可行性 dp。
设
::::info[代码]
#include <bits/stdc++.h>
#define pb push_back
#define pii pair<int, int>
// #define int long long
using namespace std;
#ifdef ONLINE_JUDGE
#define debug(...) 0
#else
#define debug(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#endif
// you need fread or not?
const int maxn = 5e2 + 10;
int n;
int A[maxn], B[maxn], f[maxn], c[maxn], d[maxn];
bool cc() {
for (int i = 1; i <= n; ++i)
if (c[i] > 1)
return 0;
return 1;
}
bool ck(int l, int r) {
for (int i = l + 1; i <= r; ++i) {
if (f[i] < 0 && A[-f[i]] != -1 && A[-f[i]] < l)
return 0;
if (f[i] > 0 && B[f[i]] != -1 && B[f[i]] > r)
return 0;
}
int len = (r - l + 1) >> 1;
for (int i = l, j = l + len; i <= l + len - 1; ++i, ++j) {
if (f[i] < 0 && f[j] > 0)
return 0;
if (f[i] && B[f[i]] != -1 && B[f[i]] != j)
return 0;
if (f[i] && f[j] && f[i] + f[j])
return 0;
}
return 1;
}
void solve() {
cin >> n;
for (int i = 1; i <= n * 2; ++i)
c[i] = d[i] = f[i] = 0;
for (int i = 1; i <= n; ++i)
cin >> A[i] >> B[i];
for (int i = 1, a, b; i <= n; ++i) {
a = A[i], b = B[i];
if (b > 0 && a > b) {
cout << "0\n";
return;
}
if (a > 0)
c[a]++, f[a] = i;
if (b > 0)
c[b]++, f[b] = -i;
}
n <<= 1;
if (!cc()) {
cout << "0\n";
return;
}
d[0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = (i & 1); j < i; j += 2)
d[i] = (d[i] | (d[j] && ck(j + 1, i)));
}
cout << d[n] << '\n';
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
cout << flush;
return 0;
}
::::