首页 > 其他分享 >2024/12/27 总结

2024/12/27 总结

时间:2024-12-17 21:42:27浏览次数:3  
标签:12 int ll 2024 fa 27 s1 dp mod

2024/12/27 总结

模拟赛 T1 取石子游戏

A和B两人玩取石子游戏。一共有n堆石子,第堆有α个石子。A和B轮流取石子,A先取,每次选择一堆然后取任意数量的石子(不能不取)。但是B必须取两次,即取石子的顺序是,ABBABB...。当一方无法取石子,则输掉游戏。假设A和B均绝顶聪明,请判断A是否可以获,胜,若A可以获胜则输出win,否则输出Lose。

序列全1的话,n % 3 != 0时先手必胜

如果序列有n-1个1,1个x的话,先手可以选择取到n个1或者n-1个1,总有一种方法能使得自己必胜。

如果序列中有k个数大于1.

对于后手:

  • k = 2时,后手可以选择把序列化为n个1 , 化为n-1个1或者n-2个1.一定有一种获胜
  • k = 1时,后手可以选择把序列化为n个1(大于1的数大于2),化为n-1个1或n-2个1. 在大于1的数大于2时一定有一种获胜。

在先手拿到的状态k = 2时,先手只能在状态为形如[1,1,1...,2,x(x%3 != 2)]时赢,即把x取干净或变为1。

当先手拿到的状态k > 2时,后手肯定可以有操作使得先手再次拿到时不存在x(x%3 != 2),也就是说这种情况中先手必败。

题就做完了,如果实在推不了的话其实也可以打表。

#include<bits/stdc++.h>
using namespace std;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	int T;
	cin >> T;
	while (T--) {
		int n, cnt1 = 0, cnt2 = 0;
		cin >> n;
		for (int i = 1; i <= n; i++) {
			int x;
			cin >> x;
			if (x == 1) cnt1++;
			if (x == 2) cnt2++;
		}
		
		// 全为1的情况
		if (cnt1 == n) {
			cout << (n % 3 == 0 ? "Lose\n" : "Win\n");
		} else {
			// 存在非1的情况
			int non_ones = n - cnt1;
			if (non_ones == 1 || (non_ones == 2 && cnt2 > 0 && n % 3 != 2)) {
				// 1个非1数字或2个非1数字且至少有1个是2
				cout << "Win\n";
			} else {
				// 其他情况
				cout << "Lose\n";
			}
		}
	}
	return 0;
}

树上字符串

有一棵n个节点的树,树上每个节点都有一个字母,再给定一个字符串S。,有q次询问,每次询问给出到,令T表示到简单路径上每个节点字符依次拼起来组成的,字符串。你需要求出T有多少个子序列和S相等,答案对998244353取模。

求出两个点的lca w。求出u到w的路径上,能匹配s的长度为x的前缀数量,令其为a[x],同理求出v到w路径上能匹配s的长度为|s| - x的后缀数量,令其为b[l - x]。

答案就是a[x] * b[l - x]。要特判一下w这个点,由于我们求的是子序列,同时考虑包含w的答案和不包含w的答案加起来即可。

接下来问题就在于如何处理a和b了。(有一些很难理解)

考虑一个dp, 设F l,r,u 为从u到根节点的路径匹配了s[l,r]子串的子序列数量,那么a[i]就等于u到根匹配了长度为i的前缀的数量, 减去a[u] (小到大递推a[i],a[u]必然已求出) 乘F u+1w,i(s[u+1,i]的子串匹配在w到根的路径的情况数)(容斥画图可理解,我不会证),同理也可以求出b[x]的。

总复杂度n * |S| ^ 2,很tm卡空间。

优化:发现dp数组中r一定会大于l,所以写个索引就可以节省一半空间,注意优化一下常数。

代码(没加优化,MLE声一片)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
constexpr ll maxn = 1e5,maxs = 35;
constexpr ll mod = 998244353;
int_least32_t dp[2][maxs][maxs][maxn];//从u节点到根的路径匹配了s0[i,j]这段子串的子序列有多少种。
ll c[maxs],d[maxs];
char s[maxn],s1[maxs];

vector<int> mp[maxn];
int p[50][maxn],fa[maxn],deep[maxn];
namespace LCA {
	void dfs(ll u){
		if(u == 1)fa[u] = 0;
		p[0][u] = fa[u];
		deep[u] = deep[fa[u]] + 1;
		for(ll i = 1;i < 20;i ++)p[i][u] = p[i-1][p[i-1][u]];
		ll sz = mp[u].size();
		for(ll i = 0;i < sz;i ++){
			ll v = mp[u][i];
			if(v == fa[u])continue;
			fa[v] = u;
			dfs(v);
		}
	}
	ll getf(ll u,ll k){
		for(ll i = 0;i < 20;i ++)
			if(k &(1 << i))
				u = p[i][u];
		return u;
	}
	ll query(ll a,ll b){
		if(deep[a] > deep[b])swap(a,b);
		b = getf(b,deep[b] - deep[a]);
		if(a == b)return a;
		for(ll i = 19;i >= 0;i--){
			if(fa[a] == fa[b])break;
			if(p[i][a] != p[i][b]){
				a = p[i][a];
				b = p[i][b];
			}
		}
		return fa[a];
	}
};

ll l;
void dfs(int u,int x,int c){
	for(int i = x;i <= l;i ++){
		dp[c][x][i][u] += dp[c][x][i][fa[u]];
		if(dp[c][x][i][u] >= mod) dp[c][x][i][u] -= mod;
		
		if(s[u] == s1[i])
			dp[c][x][i][u] += dp[c][x][i-1][fa[u]];
		if(dp[c][x][i][u] >= mod) dp[c][x][i][u] -= mod;
	}
	int sz = mp[u].size();
	for(int i = 0;i < sz;i ++){
		int v = mp[u][i];
		if(v == fa[u])continue;
		dfs(v,x,c);
	}
}

void init(ll n,ll c){
	for(int i = 0;i <= l + 1;i ++){
		for(int j = 0;j <= n;j ++){
			for(int k = 0;k <= i;k ++)
				dp[c][k][i][j] = 0;
			if(i) dp[c][i][i-1][j] = 1;
		}
	}
	for(ll i = 1;i <= l;i ++)
		dfs(1,i,c);
}

signed main() {
	//freopen("treestr2.in","r",stdin);
	ll n,q;
	cin>>n>>q;
	for(ll i = 1;i <= n;i++)mp[i].clear();
	for(ll i = 1;i < n;i ++){
		ll a,b;
		cin>>a>>b;
		mp[a].push_back(b);
		mp[b].push_back(a);
	}	
	cin>>(s + 1)>>(s1 + 1);
	l = strlen(s1 + 1);
	LCA::dfs(1);
	reverse(s1 + 1,s1 + l + 1);
	init(n,0);
	reverse(s1 + 1,s1 + l + 1);
	init(n,1);
	while(q --){
		ll a,b;
		cin>>a>>b;
		if(a == b){
			if(l == 1 && s[a] == s1[1]) cout<<1<<endl;
			else cout<<0<<endl;
			continue;
		}
		ll w = LCA::query(a,b);
		ll ans = 0;
		for(ll i = 0;i < maxs;i++) c[i] = 0;
		for(ll i = 0;i < maxs;i++) d[i] = 0;
		for(ll i = 0;i <= l;i ++){
			c[i] = dp[0][l-i+1][l][a];
			d[i] = dp[1][l-i+1][l][b];
			for(ll j = 0;j < i;j ++){
				c[i] -=(c[j] * dp[0][l-i+1][l-j][w] % mod);
				d[i] -=(d[j] * dp[1][l-i+1][l-j][w] % mod);
				c[i] += mod;
				if(c[i] >= mod)c[i] -= mod;
				d[i] += mod;
				if(d[i] >= mod)d[i] -= mod;
			}
		}
		for(ll i = 0;i <= l;i ++){
			ans += c[i] * d[l-i] % mod;
			if(ans >= mod)ans -= mod;
		}
		for(ll i = 0;i < l;i ++){
			if(s[w] == s1[i+1]){
				ans += c[i] * d[l-i-1] % mod;
				if(ans >= mod)ans -= mod;
			}
		}
		cout<<ans<<endl;
	}
	
}

一些构造好题

Black and White Tree

给您一棵 \(n\) 个节点的树,树边有边权,每个节点都有颜色,且只可能是黑色或白色(用 \(0\) 或 \(1\) 表示)。原树不存在树边连接 \(2\) 个同色的节点。

现给出每个节点的颜色和与这个节点相连的边的权值和,请您还原这棵树。

思路

一些启发/结论: 边权可以为0,整个树就相当于一个没有环的二分图。黑点所连边的权值和与白点所连边的权值和相同。

我们可以每次取出一个黑点和一个白点,将权值小的那个点权值清零,大的那个减去另一个点的权值,也就是说,一个点将他的所有权值连接到了另一个点,剩下的边权值就会为0了,我们就把权值变为0的点删掉。

一直这样做,直到没有点可以选了,由于题目保证有解,所以我们就构造完了。

标签:12,int,ll,2024,fa,27,s1,dp,mod
From: https://www.cnblogs.com/Kang-shifu/p/18613468

相关文章

  • 12 月做题记录
    12.1-12.15P11364[NOIP2024]树上查询简单题,不知道场上在干嘛,拿出\([l,r]\)只有\(O(n)\)个区间的结论,然后找出来直接扫描线就好了。实际上更好的做法是\[LCA(l,r)=\text{mindep}_{i=l}^{r-1}lca(i,i+1)\]找出来建笛卡尔树,然后扫描线应该会更好写。这个结论怎么能忘了的......
  • Crashlytics:Crashlytics自动化测试集成_2024-07-23_15-36-45.Tex
    Crashlytics:Crashlytics自动化测试集成Crashlytics自动化测试集成Crashlytics概述Crashlytics是Firebase提供的一款强大的错误报告工具,它能够帮助开发者监控和分析应用的崩溃情况,提供详细的崩溃报告,包括崩溃发生的时间、地点、设备信息、操作系统版本等,从而帮助开发者快......
  • Crashlytics在Web应用中的集成教程_2024-07-23_16-12-19.Tex
    Crashlytics在Web应用中的集成教程Crashlytics简介Crashlytics的功能与优势Crashlytics是Firebase提供的一项服务,专门用于监控和分析应用程序的崩溃情况。它能够自动收集、整理并报告应用在运行过程中遇到的错误和异常,帮助开发者快速定位问题,提高应用的稳定性和用户体验......
  • Memory Leak Detector:C++内存泄漏常见原因分析_2024-07-23_09-29-09.Tex
    MemoryLeakDetector:C++内存泄漏常见原因分析C++内存管理基础动态内存分配与释放在C++中,动态内存管理是通过new和delete操作符来实现的。new操作符用于在运行时分配内存,而delete操作符用于释放之前分配的内存。理解动态内存分配与释放的机制对于避免内存泄漏至关重要。......
  • .NET周刊【12月第2期 2024-12-08】
    国内文章终于解决了.net在线客服系统总是被360误报的问题(对软件进行数字签名)https://www.cnblogs.com/sheng_chao/p/18581139升讯威在线客服与营销系统由.netcore和WPF开发,旨在开放、开源、共享。开发者为解决360与其他国产管家的误报问题,采用数字签名以提升软件安全性。使用S......
  • 2024年最值得使用的18个Python库
    如果说Python是一把锋利的瑞士军刀,那么Python库就是它的多功能模块,让编程变得更加高效和简单。在2024年,Python生态依然蓬勃发展,各类新兴与经典库层出不穷,究竟有哪些库值得我们投入时间学习和使用?这一份清单将成为你提升生产力的利器!2024年,哪些Python库在实际开发中最具价值?无......
  • NOIP2024
    272。场上T1T2总共花了2.5h。剩下2h分配给两个难题,没有人会有心思去想正解。最后暴力调了好一会儿,花1h20min才过T4的32pts,但实际还有潜在的16pts因为时间不够没写。然后着急忙慌的去看T3,rush出40pts的送分,最后rushk=2没调出来,遗憾离场。显然我们不能对后面2......
  • 【ECCV 2024】Face Adapter for Pre-Trained Diffusion Models with Fine-Grained ID
    【ECCV2024】FaceAdapterforPre-TrainedDiffusionModelswithFine-GrainedIDandAttributeControl一、前言文章核心观点AbstractIntroduction本文的具体方法实现过程?网络的输入输出,条件是什么?损失函数是怎么设计的?网络输入输出,条件损失函数详细介绍SpatialCo......
  • Android 13 相较于 Android 12 的新特性
    标签:Android13;Android13新特性;Android13相较于Android12的新特性及开发者注意事项一、Android13相较于Android12的新特性Android13(代号Tiramisu)在用户体验、安全性、隐私保护以及开发者工具等多个方面进行了改进和增强。以下是一些主要的新特......
  • COMP2012J Operating Systems Memory Management
    OperatingSystemsAssignment02:MemoryManagementCOMP2012J2024-251MemoryManagementSimulatorPleasefindthememorymanagementsourcefilesfromthemoodle.Thissimulatorillustratespagefaultbehaviourinapagedvirtualmemorysystem.Theprogram......