若若跟我说要出三个前期/中期题,于是就有了这三个题。
C 挖矿
有个显然的想法:对于黑心资本家的检查,你被抓住的概率只和你的下矿天数有关,和你的具体下矿日期无关。
因此就变成了两个部分:对于某一个下矿天数 ,求
天下矿的最大期望收益和
天下矿不被监工发现的概率,相乘就是下矿
天的最大期望收益。然后从
枚举下矿天数,可得最大期望收益。
对于前者,可以设 表示对于前
天,下矿
次的期望最大收益,一般地,有:
注意一下边界,dp 一下就能求出来。
对于后者,考虑使用古典概型求,设 表示下矿
天监工
天不被发现的概率,有
。
其中 。
展开之后发现这个东西可以递推: pp[k][m] = (m-k+1)/(n-k+1) * pp[k-1][m]
边界:
。
。
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
using namespace std;
const int N = 5e3 + 10;
int a[N];
double p[N], f[N][N], pp[N][N];
signed main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
int n, C, x;
cin >> n >> C;
cout << n << endl;
rep(i,1,n) cin >> a[i];
rep(i,1,n) cin >> x, p[i] = x / 1000.0;
f[0][0] = 0;
rep(i,1,n) {
f[i][0] = 0;
rep(k,1,i-1)
f[i][k] = max(f[i - 1][k], (f[i - 1][k - 1] + a[i]) * (1 - p[i]));
f[i][i] = (f[i - 1][i - 1] + a[i]) * (1 - p[i]);
}
pp[0][0] = 1;
rep(m,1,n) {
pp[0][m] = 1;
rep(k,1,min(m,n)) pp[k][m] = pp[k - 1][m] * (m - k + 1) / (n - k + 1);
}
cout.setf(ios::fixed);
cout.precision(12);
rep(k,0,n) {
double ans = 0;
rep(j,0,n) ans = max(ans, (C + f[n][j] / 5) * pp[k][j]);
cout << ans << ' ';
}
cout << endl;
return 0;
}
H 数学
对于分解为 的数,可以用
的时间枚举平方根,共
。
对于分解为 的数,可以分别枚举组成它的两个平方数(取值集大小
,由上一步求出)是什么,时间复杂度
,然后剔除掉只分解为
的数。
分解为 的数同样可以参照上面的方法在
求出。
根据拉格朗日四数平方和定理,剩下的数分解数为 。
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define pb push_back
using namespace std;
const int N = 1e5 + 10, mod = 998244353;
int f[N];
inline bool sq(int x) {
int p = sqrt(x);
return p * p == x;
}
signed main() {
int n;
cin >> n;
vector<int> v, w;
for(int i = 1; i * i <= n; ++ i) {
f[i * i] = 1;
v.pb(i * i);
}
for(int x : v)
for(int y : v) {
if(x + y > n) break;
if(!f[x + y]) {
f[x + y] = 2;
w.pb(x + y);
}
}
for(int y : w)
for(int x : v) {
if(x + y > n) break;
if(!f[x + y]) f[x + y] = 3;
}
int ans = 1;
rep(i,1,n) {
if(!f[i]) f[i] = 4;
ans = 1ll * ans * f[i] % mod;
}
cout << ans << endl;
return 0;
}
I 电梯
对不起,题面写了依托答辩。
只需要维护一下电梯运行的状态,仔细判断何时上下客即可。
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define pb push_back
using namespace std;
const int N = 1e5 + 10;
int t[N], a[N], b[N], ans[N];
queue<int> up[N], down[N];
struct node {
int id;
node() {}
node(int x) : id(x) {}
bool operator < (const node &o) const { return b[id] < b[o.id]; }
bool operator > (const node &o) const { return b[id] > b[o.id]; }
};
priority_queue<node> inn;
priority_queue<node,vector<node>,greater<node>> in;
int cnt;
signed main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
int q, K, C = 0, task = 0;
cin >> q >> K;
rep(i,1,q) {
cin >> t[i] >> a[i] >> b[i];
C = max(C, max(a[i], b[i]));
}
int p = 1, flr = 1, state = 0;
for(int tm = 0; ; ++ tm) {
if(task == q) break;
// unload
if(state == 1)
while(!in.empty() && b[in.top().id] == flr) {
ans[in.top().id] = tm;
in.pop(); -- cnt; ++ task;
}
if(state == 2)
while(!inn.empty() && b[inn.top().id] == flr) {
ans[inn.top().id] = tm;
inn.pop(); -- cnt; ++ task;
}
// add item by order
vector<int> inc;
while(p <= q && t[p] <= tm) { inc.pb(p); ++ p; }
stable_sort(inc.begin(), inc.end(), [&](int x, int y) {
return t[x] < t[y] || (t[x] == t[y] && abs(a[x] - b[x]) < abs(a[y] - b[y]));
});
for(int x : inc) {
if(a[x] < b[x]) up[a[x]].push(x);
else down[a[x]].push(x);
}
// modify state
bool hasupper = false, haslower = false;
rep(i,flr+1,C) if(up[i].size() || down[i].size()) { hasupper = true; break; }
if(cnt < K && up[flr].size()) hasupper = true;
rep(i,1,flr-1) if(up[i].size() || down[i].size()) { haslower = true; break; }
if(cnt < K && down[flr].size()) haslower = true;
if(state == 0) {
if((cnt < K && up[flr].size()) || hasupper) state = 1;
else if((cnt < K && down[flr].size()) || haslower) state = 2;
} else if(state == 1) {
if(!hasupper && cnt == 0) state = 0;
} else if(state == 2) {
if(!haslower && cnt == 0) state = 0;
}
// load users
if(state == 1) {
while(cnt < K && up[flr].size()) {
in.push(up[flr].front()); up[flr].pop(); ++ cnt;
}
} else if(state == 2) {
while(cnt < K && down[flr].size()) {
inn.push(down[flr].front()); down[flr].pop(); ++ cnt;
}
}
// modify floor
if(state == 1) ++ flr;
else if(state == 2) -- flr;
}
rep(i,1,q) cout << ans[i] << ' ';
cout << endl;
return 0;
}