其他分享
首页 > 其他分享> > 八一特别行动

八一特别行动

作者:互联网

题目背景:(为啥放图片你可以猜猜)

image

image

A. 南

设\(g_i\)表示有\(i\)种武器,要拿到\(n\)种的期望花费

根据拿到与已有武器种类是否相同的概率,显然有

\(g_i = \frac{i}{n}g_i + \frac{n - i}{n}g_{i + 1} + cost\)

\(cost\)为该次购买对总期望的贡献,每次购买会令后面所有购买花费\(+1\),那么实际上\(cost\)就是期望次数

与之前相同,显然有

\(f_i = \frac{i}{n}f_i + \frac{n - i}{n}f_{i + 1} + 1\)

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. 昌

考场贪心假了

设\(f_i\)表示\(i\)是子树内第\(f_i\)大的数

对取\(min\)是对子节点求和

取\(max\)是取子节点最小值

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. 起

预处理中心扩展出的最大矩形

查询二分答案,对比边界小答案的子矩形求最值,如果大于等于当前答案,那么存在

这样实际上保证了一定至少有\(mid\)的扩展在询问内

rt
image

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;
}

根号分治,小于根号的直接背包,用\(DZYlovesmath\)那种优化

大于根号的另设一种\(dp\)

显然选取不会超过\(\sqrt n\)个

\(g[i][j]\) 表示选取了\(i\)个,容量为\(j\)的方案数

考虑都由大小为\(\sqrt n + 1\)的物品变化而成

两种操作

  1. 对每个物品大小 + 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;
}

标签:特别,八一,return,int,mid,len,maxn,行动,include
来源: https://www.cnblogs.com/Chencgy/p/16543360.html