首页 > 其他分享 >AT_arc175_a [ARC175A] Spoon Taking Problem 题解

AT_arc175_a [ARC175A] Spoon Taking Problem 题解

时间:2024-03-25 13:47:45浏览次数:19  
标签:右边 第一个 左边 Taking arc175 题解 define 勺子 out

题目翻译 link

有 \(N\) 人围坐在一张圆桌旁,按逆时针顺序编号为 \(1\) 至 \(N\) 。每个人都有一个惯用手

圆桌上有 \(N\) 把勺子,编号为 \(1\) 到 \(N\) ,每对相邻的人之间放一把勺子

给你一个 \((1, \dots, N)\) 的排列组合 \((P_1, \dots, P_N)\) 。在 \(i=1,\dots,N\) 的顺序中,人 \(P_i\) 的行为如下:

  • 如果两边都有剩余的勺子,他们会拿自己惯用手一边的勺子
    • 如果左侧或右侧有剩余的勺子,他们将拿走其中一个
  • 否则,他们什么也不会做

给出了一个长度为 \(N\) 的字符串 \(S\) ,由 LR?组成:

  • 如果 \(S_i\) 是 "L",那么 \(i\) 是左撇子
  • 如果 \(S_i\) 是 "R",那么 \(i\) 是右撇子

在 \(2^N\) 个可能的主手组合中,找出有多少个满足以下所有条件的 \(s\),模数为 \(998244353\) :

当每个人都行动完后,每个人都拿了一把勺子

方法

法一

暴力枚举每种可能的 \(s\) ,然后检验

时间复杂度 \(O_{(2^X \times N)}\) , \(X\) 为 ? 的个数

法二

分析

我们可以发现对于一个满足条件的 \(S\) ,每个人都应该拿与第一个拿的人同侧的勺子

于是:

我们可以分类讨论

讨论第一个拿的人是拿左边还是右边:

  • 若为 R 只讨论右边
  • L 只讨论左边
  • ? 讨论两种最后求和

每个人拿的方向应与第一个拿的人一致,然后找规律

规律

(注:这里类似 “ \(P_i\) 为 L ” 的语句其实是 “ \(S[P_i]\) 为 L ” ,为了简便记作 \(P_i\) )

若第一个拿的人拿左边

对于第 \(P_i\) 个人来说

  • 如果他右边的人 \(r\) 已经先拿过他左边的勺子,那么 \(P_i\) 可以为 LR ,那么 \(ans\) 乘 \(2\) (注意,若 \(P_i\) 确定, \(ans\) 不变)
  • 如果他右边的人 \(r\) 后拿,那么他只能拿左边的勺子, \(ans\) 不变
  • 如果他右边的人 \(r\) 没有先拿过他左边的勺子且 \(P_i=\) R ,那么第一个拿的人拿左边的情况误解,即 \(ans=0\)

若第一个拿的人拿右边,可类似若第一个拿的人拿左边推出

这里为了简短就不写啦

注意取模!!!你猜我怎么知道的 警示后人

代码实现:

#include<bits/stdc++.h>
#define put(n) scanf("%lld",&n) 
#define out(n) printf("%lld\n",n)
#define int long long
#define fd(i,a,b) for(int i=a;i<=b;i=-~i)
using namespace std;
int n,p[1000100],f[1000100],mod=998244353;
//f记录第i个人第几个拿
char s[1000100];
int ans1=1,ans2=1;// 拿左边 拿右边
signed main()
{
	put(n);
	fd(i,1,n) put(p[i]),f[p[i]]=i;
	fd(i,1,n) cin>>s[i];
	//第一个拿的人拿左边
	fd(i,1,n)
	{
		int r=p[i]+1;//r 当前拿的人右边的人的编号
		if(r==n+1) r=1;//小坑
		if(s[p[i]]=='?')
		{
			if(f[r]<i) ans1*=2;
			ans1%=mod;
		}
		else if(s[p[i]]=='R')
		{
			if(f[r]>i)
			{
				i=n+1;
				ans1=0;
				break;
			}
		}
	}
	//第一个拿的人拿右边
	fd(i,1,n)
	{
		int l=p[i]-1;//l 当前拿的人左边的人的编号
		if(l==0) l=n;//小坑
		if(s[p[i]]=='?')
		{
			if(f[l]<i) ans2*=2;
			ans2%=mod;
		}
		else if(s[p[i]]=='L')
		{
			if(f[l]>i)
			{
				i=n+1;
				ans2=0;
				break;
			}
		}
	}
	if(s[p[1]]=='R') out(ans2);
	else if(s[p[1]]=='L') out(ans1);
	else out((ans1+ans2)%mod);//如果Pi为?那么算两种情况之和
	return 0;
}

无关的话(审核大大,求过审):被禁言了,怎么解啊?

感谢观看

标签:右边,第一个,左边,Taking,arc175,题解,define,勺子,out
From: https://www.cnblogs.com/whrwlx/p/18094188

相关文章

  • 题解:AT_abc345_c [ABC345C] One Time Swap
    求过审题面翻译给定一个字符串$s$,求执行以下操作一次可以产生的字符串的个数设$N$为$s$的长度。选择一对整数$(i,j)$,使$1≤i<j≤N$,交换$s$的第$i$个和第$j$个字符可以证明,在这个问题的约束条件下,你总是可以得到它思路暴力做法我们可以......
  • JavaScript:void(0) 用法及常见问题解析
    JavaScript:void(0)用法及常见问题解析javascript:void(0);是一种在JavaScript和网页开发中经常使用的技术,尤其在处理链接的行为时。本文将深入探讨javascript:void(0);的用法,以及在使用过程中可能遇到的常见问题和解决方法。什么是javascript:void(0);?javascript:v......
  • LeetCode第390场周赛题解(c++)
    真的无语了,早上怎么都提交不了,显示未知错误。。。结果晚上就可以提交了。唉100245.每个字符最多出现两次的最长子字符串给你一个字符串 s ,请找出满足每个字符最多出现两次的最长子字符串,并返回该子字符串的 最大 长度。示例1:输入: s="bcbbbcba"输出: 4解释:以......
  • [题解]HDU1024 Max Sum Plus Plus
    HDU1024这道题是一道很巧妙的\(dp\)题(虽然优化成一维,可是究其本质算不算二维\(dp\)?如果有明白的麻烦在评论说一下多谢),在上一篇文章——线性\(dp\)模型中也提到过,因为其前身其实就是上一篇写到的「最大连续子段和」。只不过这一题问的不是一段,而是\(m\)段,所以较上一题我们的选择......
  • AtCoder Beginner Contest 346 题解
    A-AdjacentProductQuestion给你\(N\)个整数\(A_1,A_2,\dots,A_N\)。同时,定义\(B_i=A_i\timesA_{i+1}\(1\leqi\leqN-1)\)按此顺序打印\(B_1,B_2,\dots,B_{N-1}\)Solution按照题意模拟Code#include<bits/stdc++.h>usingnamespacestd;intmain......
  • AT_abc344_D-String Bags 题解
    明显是DP。然后就开始分析:状态:\(dp_{ij}=\)有\(i\)个袋子且匹配\(T\)的前缀的长度为\(j\)时所需的最少钱数。匹配\(T\)的前缀的长度为\(j\)就是前\(j\)个字符与\(T\)的前\(j\)个字符相同。相对简单。然后看转移。为了方便,咱不妨令\(|S|\)为字符串\(S......
  • P10111 [GESP202312 七级] 纸牌游戏 题解
    看标签知道要用DP。于是开始分析。状态:$dp(i,j,k)=$前\(i\)轮中,第\(i\)轮出\(j\),一共换了\(k\)次牌的最大钱数。很好理解。转移也不难,不就是不换和换两种吗!所以,转移就是:\[dp(i,j,k)=\max\begin{cases}dp(i-1,j,k)+\operatorname{pk}(j,c_i)\times......
  • [暴力题解系列]2023年蓝桥杯-整数删除(30分)
    这题暴力最多30分,但是30分也是分,做暴力的人不能贪心,拿到分就是赚了。​ 这题核心烦人点在于他数据分层断崖,就只有前3个点能做到稳过。用的思路就是链表,但不是用指针存的,而是用数组下标为标记存的,只是我觉得因为这样好写一些。链表方便修改左右连接位置,所以越到后面就越能省下查询......
  • 0318-0324题解
    成信大天梯赛L1-6二进制因为二进制是逢二进一,所以我们只要用cnt记录一下每一位上的数并给它加起来,然后cnt%2便是其和这一位上的数,注意要从右往左开始点击查看代码#include<bits/stdc++.h>usingnamespacestd;typedefpair<int,int>pii;voidsolve(){stringa,b......
  • 广州大学第十八届ACM大学生程序设计竞赛(同步赛)——题解
    这套题我答的很失败。没有按照题目的难度去答题,前期浪费了不少时间。题目:A-字符画题解:思维、模拟。这道题我的通过率为62.5,没有过的原因是因为对细节的处理和把控不到位,对一些点忽视,我也记录了搜索的过程,但没有把搜索过的点消掉,而且没有找到最好的顺序去解答这道题,我是按照横的......