2024.9.25 模拟赛 多校

模拟赛

假做法上大分。

T1 几何

bitset 优化 dp。有空学,先挂个暴力。

code
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5+5;
int T,n,m,t;
char s[N],x[55],y[55];
unordered_map<int,unordered_map<int,bool> >f[N];
unordered_map<int,unordered_map<int,bool> >vs[N];

bool dfs(int p,int nx,int ny)
{
	if(p==t+1) return (nx==n&&ny==m);
	if(vs[p][nx][ny]) return f[p][nx][ny];
	if(s[p]==x[nx%n+1]) if(dfs(p+1,nx%n+1,ny)) return 1;
	if(s[p]==y[ny%m+1]) if(dfs(p+1,nx,ny%m+1)) return 1;
	vs[p][nx][ny]=1;
	return f[p][nx][ny]=0;
}

int main ()
{
	freopen("geometry.in","r",stdin);
	freopen("geometry.out","w",stdout);
	scanf("%d",&T);
	while(T--)
	{
		scanf("%s%s%s",s+1,x+1,y+1);
		n=strlen(x+1),m=strlen(y+1),t=strlen(s+1);
		for(int i=1;i<=t;i++) f[i].clear(),vs[i].clear();
		if(dfs(1,n,m)) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

T2 分析

又是一道树上 dp。。。

发现问题和一笔画问题有点像,也就是如果一条路径能一笔画完就没有代价,每个点的度数都为偶数时能一笔画完,所以关键在度数为奇数的点的个数。

为了确定度数,我们先进行 A 操作,A 操作可以直接看成加重边,对于加完 A 操作的图,如果还存在奇数的点(一笔画不完),那么就需要 B 来补。

显然,如果存在 \(k\) 个度数为奇数的点,那么代价就是 \(\frac{k}{2}-1\)(每跳一次消掉两个点,起点没代价)。

\(\frac{1}{2}\) 看起来不太好做,但发现性质:度数为奇数的点只会有偶数个。所以每次加边删边都会改变 \(2\) 个点度数的奇偶性,因此可做。

注意有一个 \(-1\),如果需要 B 操作才用减,如果根本没用过 B 当然不能减,所以我们需要知道是否有度数为奇数的点。

设计状态 \(f_{u,0/1/2}\) 表示以 \(u\) 为根:

  • 0:包括根在内整颗子树没有度数为奇数的点。
  • 1:根的度数为奇数。(因为任意一个图内度数为奇数的点有偶数个,所以子树内一定还有一个)
  • 2:根的度数为偶数,子树内有度数为奇数的点。

转移过程枚举是否加重边,然后考虑度数变化。

转移很长。。。

code
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 5e5+5;
int n;
LL f[N][3],g[3],A,B;
vector<int> e[N];

void dfs(int u,int fa)
{
	for(int v:e[u])
	{
		if(v==fa) continue;
		dfs(v,u);
		g[0]=f[u][0]+f[v][0]+A;
		g[1]=min({f[u][0]+min(f[v][0],f[v][2])+B,f[u][2]+min(f[v][2],f[v][0])+B,f[u][2]+f[v][1],f[u][0]+f[v][1],f[u][1]+min({f[v][0],f[v][1],f[v][2]})+A});
		g[2]=min({f[u][2]+min({f[v][0],f[v][1],f[v][2]})+A,f[u][0]+min(f[v][1],f[v][2])+A,f[u][1]+min(f[v][0],f[v][2]),f[u][1]+f[v][1]-B});
		f[u][0]=g[0]; f[u][1]=g[1]; f[u][2]=g[2];
	}
}

int main()
{
	freopen("analyse.in","r",stdin);
	freopen("analyse.out","w",stdout);
	scanf("%d%lld%lld",&n,&A,&B); A=min(A,B);
	for(int i=1;i<=n;i++) f[i][1]=f[i][2]=1e17;
	for(int i=1;i<n;i++)
	{
		int x,y; scanf("%d%d",&x,&y);
		e[x].push_back(y); e[y].push_back(x);
	}
	dfs(1,0);
	printf("%lld\n",min({f[1][0],f[1][1]-B,f[1][2]-B}));
	return 0;
}

T3 代数

考虑子树大小的 \(k\) 次方的组合意义,\(n^k\) 的组合意义:\(n\) 个点任选 \(k\) 个,可重有序。

咕咕咕。。。

T4 组合

构造 \(26\)\(1000\) 位的二进制数,使两两按位或得到的值不同。

咕咕咕。。。

posted @ 2024-10-10 16:57  ppllxx_9G  阅读(18)  评论(1编辑  收藏  举报