CSP-S模拟5

???博客园自动保存呢?

我刚打完就没了?????

下次一定本地写

因为某些原因,原来写完的题解突然没了,于是有了现在这个

下次一定在本地写

A. F

枚举 a1 和哪个数异或然后暴力检查即可

不会有人跟我一样傻打 Tire

code
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2005;
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;
}
int n, a[maxn], b[maxn], idb[maxn];
struct tire{
	int ch[1000005][2], size[1000005], root = 1, cnt = 1;
	int insert(int x){
		int now = root;
		for(int i = 30; i >= 0; --i){
			int s =  (x >> i) & 1;
			if(!ch[now][s])ch[now][s] = ++cnt;
			now = ch[now][s];
		}
		++size[now];
		return now;
	}
	int sta[maxn];
	bool check(int x){
		int top = 0, flag = 1;
		for(int i = 2; i <= n; ++i){
			int now = root;
			for(int j = 30; j >= 0; --j){
				if(!now){flag = 0; break;}
				if((x >> j) & 1)now = ch[now][1 xor ((a[i] >> j) & 1)];
				else now = ch[now][(a[i] >> j) & 1];
			}
			if(!now || size[now] == 0){flag = 0; break;}
			--size[now]; sta[++top] = now;
			if(!flag)break;
		}
		for(int i = top; i > 0; --i)++size[sta[i]];
		return flag;
	}
}t;
set<int>ans;
int main(){
	freopen("f.in","r",stdin);
	freopen("f.out","w",stdout);
	n = read();
	for(int i = 1; i <= n; ++i)a[i] = read();
	for(int i = 1; i <= n; ++i)b[i] = read();
	for(int i = 1; i <= n; ++i)idb[i] = t.insert(b[i]);
	for(int i = 1; i <= n; ++i){
		int x = (a[1] xor b[i]);
		if(ans.count(x))continue;
		--t.size[idb[i]];
		if(t.check(x))ans.insert(x);
		++t.size[idb[i]];
	}
	printf("%d\n",(int)ans.size());
	for(int x : ans)printf("%d\n",x);
	return 0;
}

B. S

dpi,j,k,0/1/2 表示填了前 i 个位置, 用了 jR, kG 最后一个填的是 R/G/Y

转移枚举下一个填啥

发现同一种颜色之间的相对位置不会改变,所以可以方便知道下一个填的颜色原来的位置

发现新位置为原位置 + 移到他前面的颜色的个数

预处理每个位置前面有多少某种颜色,然后就可以方便转移了

code
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const int maxn = 4005;
const int inf = 0x3f3f3f3f;
int n; char c[maxn];
int cr, cg, cy;
int cnt[maxn][3], posr[maxn], posg[maxn], posy[maxn];
int f[2][maxn][maxn][3];
int main(){
	// freopen("s.in","r",stdin);
	// freopen("s.out","w",stdout);
	scanf("%d%s",&n,c + 1);
	for(int i = 1; i <= n; ++i){
		if(c[i] == 'R')posr[++cr] = i;
		else if(c[i] == 'G')posg[++cg] = i;
		else if(c[i] == 'Y')posy[++cy] = i;
		cnt[i][0] = cr; cnt[i][1] = cg; cnt[i][2] = cy;
	}
	if(max(max(cr, cg), cy) > (n + 1) / 2){
		printf("-1\n");return 0;
	}
	memset(f, 0x3f, sizeof(f));
	f[1][1][0][0] = posr[1] - 1;
	f[1][0][1][1] = posg[1] - 1;
	f[1][0][0][2] = posy[1] - 1;
	for(int i = 1; i < n; ++i){
		int zt = i & 1, nzt = 1 - zt;
		for(int x = 0; x <= cr; ++x){
			if(x > i)break;
			for(int y = 0; y <= cg; ++y){
				if(x + y > i)break;
				int z = i - x - y;
				if(z > cy)continue;
				int pr = posr[x + 1], pg = posg[y + 1], py = posy[z + 1];
				int dr = pr - i - 1 + max(0, y - cnt[pr][1]) + max(0, z - cnt[pr][2]);
				int dg = pg - i - 1 + max(0, x - cnt[pg][0]) + max(0, z - cnt[pg][2]);
				int dy = py - i - 1 + max(0, x - cnt[py][0]) + max(0, y - cnt[py][1]);
				if(x < cr)f[nzt][x + 1][y][0] = min(f[nzt][x + 1][y][0], min(f[zt][x][y][1], f[zt][x][y][2]) + dr);
				if(y < cg)f[nzt][x][y + 1][1] = min(f[nzt][x][y + 1][1], min(f[zt][x][y][0], f[zt][x][y][2]) + dg);
				if(z < cy)f[nzt][x][y][2] = min(f[nzt][x][y][2], min(f[zt][x][y][0], f[zt][x][y][1]) + dy);
			}
		}
		for(int a = 0; a <= cr; ++a)for(int b = 0; b <= cg; ++b)f[zt][a][b][0] = f[zt][a][b][1] = f[zt][a][b][2] = inf; 
	}
	printf("%d\n",min(min(f[n & 1][cr][cg][0], f[n & 1][cr][cg][1]), f[n & 1][cr][cg][2]));
	return 0;
}

C. Y

每个人都传给下一个人至少一个球,那么可以等价所有人拿回若干个,至少有一个人不给下一个人传球

枚举第一个这样的人,断环,

dpi,j 表示第i 个人传给下一个人 j 个球

dpi,j=dpi1,k(k+a[i]j)

然后发现我们只需要维护 dpi,j dpi,j×j

然后转移可以写成矩阵,,每次取的是一个前缀和一个后缀,预处理出来即可

我还不知道 i2=n(n+1)(2n+1)6

(n+1)3n3=3n2+3n+1

n3(n1)3=3(n1)2+3(n1)+1

....

2313=3+3+1

左右相加移项即可

Lyin 从数奥大佬 (Lyin 说是姐姐?)那里搞来的方法

code
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1000005;
const int mod = 1e9 + 7;
const int inv2 = 500000004;
const int inv6 = 166666668;
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;
}
int a[maxn], n, ans;
int dc(int l, int r, int x){
	if(r < l)return 0;
	return 1ll * (r + l) * x % mod * inv2 % mod; 
}
int sf(int x){
	return 1ll * x * (x + 1) % mod * (x + x + 1) % mod * inv6 % mod;
}
struct matrix{
	int a[2][2];
	matrix(){a[0][0] = a[0][1] = a[1][0] = a[1][1] = 0;}
	void unlimit(int x){
		int s1 = dc(1, x, x), s2 = sf(x);
		a[0][0] = s1; a[0][1] = (1ll * s1 * x % mod - s2 + mod) % mod;
		a[1][0] = x + 1; a[1][1] = s1;
	}
	void limit(int x){
		int s1 = dc(1, x, x), s2 = sf(x);
		a[0][0] = dc(1, x - 1, x - 1); a[0][1] = (1ll * s1 * x % mod - s2 + mod) % mod;
		a[1][0] = x; a[1][1] = s1;
	}
	friend matrix operator * (const matrix &x, const matrix &y){
		matrix c;
		for(int i = 0; i <= 1; ++i)
			for(int k = 0; k <= 1; ++k)
				for(int j = 0; j <= 1; ++j)
					c.a[i][j] = (c.a[i][j] + 1ll * x.a[i][k] * y.a[k][j] % mod) % mod;
		return c;
	}
}m[maxn + maxn];

int main(){
	freopen("y.in","r",stdin);
	freopen("y.out","w",stdout);
	n = read();
	for(int i = 1; i <= n; ++i)a[i] = read();
	for(int i = 1; i <= n; ++i)m[i].unlimit(a[i]);
	for(int i = 1; i <= n; ++i)m[i + n].limit(a[i]);
	for(int i = n + 2; i <= n + n; ++i)m[i] = m[i - 1] * m[i];
	for(int i = n - 1; i > 0; --i)m[i] = m[i] * m[i + 1];
	int ans = 0;
	for(int l = 1; l <= n; ++l){
		matrix now; now.a[0][0] = 1;
		if(l != n)now = now * m[l + 1];
		if(l != 1)now = now * m[l + n - 1];
		ans = (ans + 1ll * now.a[0][0] * a[l] % mod + now.a[0][1]) % mod;
	}
	ans = (ans % mod + mod) % mod;
	printf("%d\n",ans);
	return 0;
}

1

22

333

....

nnnnnn...nnn

写成正三角型,转 60 120 得到两个三角和原来的对应相加每个位置都变成了 2n+1 一共 1+2+....+n(n+1)/2 个数

可惜放不了图片(姐姐?的字写的挺好看)

D. O

upd : 写了。题解,感谢 Delov大佬的耐心讲解,我的做法跟他在处理某些细节上略有不同(比他少棵线段树)

咕了

Delov 拼凑了一个 90pts 水了一发

image

posted @   Chen_jr  阅读(67)  评论(4编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示