八一特别行动
题目背景:(为啥放图片你可以猜猜)
A. 南
设表示有种武器,要拿到种的期望花费
根据拿到与已有武器种类是否相同的概率,显然有
为该次购买对总期望的贡献,每次购买会令后面所有购买花费,那么实际上就是期望次数
与之前相同,显然有
code
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 10005;
double f[maxn], g[maxn];
int main(){
int x; scanf("%d",&x);
double n = x;
for(int i = x - 1; i >= 0; --i){
f[i] = f[i + 1] + n / (n - i);
g[i] = g[i + 1] + n / (n - i) * f[i];
}
printf("%.2lf\n",g[0]);
return 0;
}
B. 昌
考场贪心假了
设表示是子树内第大的数
对取是对子节点求和
取是取子节点最小值
code
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 300005;
inline int read(){
int x = 0; char c = getchar();
while(c < '0' || c > '9') c = getchar();
do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
return x;
}
queue<int>q;
int n,op[maxn],fa[maxn], f[maxn], rd[maxn];
int main(){
n = read();
for(int i = 1; i <= n; ++i)op[i] = read();
for(int i = 2; i <= n; ++i)++rd[fa[i] = read()];
int k = 0;
for(int i = 1; i <= n; ++i)if(!rd[i])++k;
for(int i = 1; i <= n; ++i)if(!rd[i])q.push(i),f[i] = 1;
while(!q.empty()){
int x = q.front(); q.pop();
if(fa[x]){
--rd[fa[x]];
if(rd[fa[x]] == 0)q.push(fa[x]);
if(op[fa[x]]){
if(!f[fa[x]])f[fa[x]] = f[x];
else f[fa[x]] = min(f[fa[x]], f[x]);
}else f[fa[x]] += f[x];
}
}
printf("%d\n",k - f[1] + 1);
return 0;
}
C. 起
预处理中心扩展出的最大矩形
查询二分答案,对比边界小答案的子矩形求最值,如果大于等于当前答案,那么存在
这样实际上保证了一定至少有的扩展在询问内
rt
code
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 505;
int n, m, q;
char c[maxn];
int b[maxn][maxn], w[maxn][maxn], p[maxn][maxn], g[maxn][maxn];
int col[maxn][maxn], ml[maxn][maxn];
bool check(int x, int y,int len){
int size = len * len;
if(b[x][y] - b[x][y - len] - b[x - len][y] + b[x - len][y - len] != size)return false;
if(w[x][y + len] - w[x][y] - w[x - len][y + len] + w[x - len][y] != size)return false;
if(p[x + len][y] - p[x][y] - p[x + len][y - len] + p[x][y - len] != size)return false;
if(g[x + len][y + len] - g[x][y + len] - g[x + len][y] + g[x][y] != size)return false;
return true;
}
void mr(int i,int j){
int l = 2, r = min(min(i, j),min(n - i , m - j)), ans = 1;
while(l <= r){
int mid = (l + r) >> 1;
if(check(i, j, mid))ans = mid, l = mid + 1;
else r = mid - 1;
}
ml[i][j] = ans;
}
struct ST{
int st[maxn][maxn][21][21];
void prework(){
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
st[i][j][0][0] = ml[i][j];
for(int k = 0; (1 << k) <= n; ++k)
for(int l = 0; (1 << l) <= m; ++l)
if(k || l){
if(l){
for(int i = 1; i + (1 << k) - 1 <= n; ++i)
for(int j = 1; j + (1 << l) - 1 <= m; ++j)
st[i][j][k][l] = max(st[i][j][k][l - 1], st[i][j + (1 << (l - 1))][k][l - 1]);
}
else{
for(int i = 1; i + (1 << k) - 1 <= n; ++i)
for(int j = 1; j + (1 << l) - 1 <= m; ++j)
st[i][j][k][l] = max(st[i][j][k - 1][l], st[i + (1 << (k - 1))][j][k - 1][l]);
}
}
}
int query(int a, int b, int c, int d){
if(c < a || d < b)return 0;
int k = log2(c - a + 1), l = log2(d - b + 1);
return max(max(st[a][b][k][l], st[c - (1 << k) + 1][b][k][l]), max(st[a][d - (1 << l) + 1][k][l], st[c - (1 << k) + 1][d - (1 << l) + 1][k][l]));
}
}s;
bool check(int a, int b, int c, int d, int len){
return s.query(a + len - 1, b + len - 1, c - len, d - len) >= len ? 1 : 0;
}
int mrr(int a, int b, int c, int d){
int l = 1, r = min(c - a + 1,d - b + 1) / 2, ans = 0;
while(l <= r){
int mid = (l + r) >> 1;
if(check(a, b, c, d, mid))ans = mid, l = mid + 1;
else r = mid - 1;
}
return ans * ans * 4;
}
int main(){
scanf("%d%d%d", &n, &m, &q);
for(int i = 1; i <= n; ++i){
scanf("%s",c + 1);
for(int j = 1; j <= m; ++j){
if(c[j] == 'B')col[i][j] = 1;
if(c[j] == 'W')col[i][j] = 2;
if(c[j] == 'P')col[i][j] = 3;
if(c[j] == 'G')col[i][j] = 4;
}
}
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if(col[i][j] == 1)b[i][j] = 1;
else if(col[i][j] == 2)w[i][j] = 1;
else if(col[i][j] == 3)p[i][j] = 1;
else g[i][j] = 1;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
b[i][j] = b[i][j] + b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
w[i][j] = w[i][j] + w[i - 1][j] + w[i][j - 1] - w[i - 1][j - 1];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
p[i][j] = p[i][j] + p[i - 1][j] + p[i][j - 1] - p[i - 1][j - 1];
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
g[i][j] = g[i][j] + g[i - 1][j] + g[i][j - 1] - g[i - 1][j - 1];
for(int i = 1; i < n; ++i)
for(int j = 1; j < m; ++j)
if(col[i][j] == 1 && col[i][j + 1] == 2 && col[i + 1][j] == 3 && col[i + 1][j + 1] == 4)
mr(i, j);
s.prework();
for(int i = 1; i <= q; ++i){
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
printf("%d\n",mrr(a, b, c, d));
}
return 0;
}
义
根号分治,小于根号的直接背包,用那种优化
大于根号的另设一种
显然选取不会超过个
表示选取了个,容量为的方案数
考虑都由大小为的物品变化而成
两种操作
- 对每个物品大小 + 1
2 加入新物品
code
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005;
const int mod = 23333333;
int f[maxn],n,g[333][maxn];
int main(){
scanf("%d", &n);
int m = sqrt(n);
f[0] = 1;
for(int i = 1; i <= m; ++i){
for(int j = i; j <= n; ++j)
f[j] = (f[j] + f[j - i]) % mod;
long long up = 1ll * i * (i + 1);
for(int j = n; j >= up; --j) f[j] = (f[j] - f[j - up] + mod) % mod;
}
g[0][0] = 1;
for(int i = 0; i <= m; ++i){
for(int j = 0; j <= n; ++j){
if(j + i <= n && i)g[i][i + j] = (g[i][i + j] + g[i][j]) % mod;
if(j + m + 1 <= n)g[i + 1][j + m + 1] = (g[i + 1][j + m + 1] + g[i][j]) % mod;
}
}
++g[1][0];
int ans = 0;
for(int i = 0; i <= n; ++i){
for(int j = 1; j <= m; ++j){
ans = (ans + 1ll * f[i] * g[j][n - i] % mod) % mod;
}
}
printf("%d\n",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】