首页 > 其他分享 >CodeForces - 1984F

CodeForces - 1984F

时间:2024-07-12 14:51:40浏览次数:17  
标签:PS le return int CodeForces tot 1984F

分析

考虑相邻两个字符带来的约束。

  • 若为 "SS",则满足 $|b_i-b_{i+1}| \le m $
  • 若为 "PP",则满足 \(|b_{i+1}-b_i| \le m\)
  • 若为 "PS",则满足 \(tot_a=b_i+b_{i+1}\)
  • 若为 "SP",则满足 \(tot_a+a_{i}+a_{i+1}=b_i+b_{i+1}\)

发现可以枚举 "PS" 的位置来确定 \(tot_a\),为了防止全是 "S" 或 "P" 的情况,钦定 \(s_0=P,s_{n+1}=S\)。
考虑确定了 \(tot_a\) 的情况下求出总方案数,可以设状态 \(dp_{i,0/1}\) 表示第 \(i\) 个选择了 S/P 的方案,转移比较显然,具体见代码。

代码

bool checkP(int i){
	return (s[i]=='P'||s[i]=='?');
}
		
bool checkS(int i){
	return (s[i]=='S'||s[i]=='?');
}
		
void Main(){
	mp.clear();
	int n=rd,m=rd,ans=0;
	scanf("%s",s+1);
	for(int i=1;i<=n;i++)
		b[i]=rd;
	b[0]=b[n+1]=0;
	s[0]='P',s[n+1]='S';
	for(int p=0;p<=n;p++){
		if(!checkP(p)||!checkS(p+1))
			continue;
		for(int i=0;i<=n+1;i++)
			dp[i][0]=dp[i][1]=0;
		dp[0][1]=1;
		int tot=b[p]+b[p+1];
		if(mp.count(tot)) 
			continue;
		mp[tot]=1;
		for(int i=1;i<=n+1;i++){
			if(checkS(i)){
				if(abs(b[i-1]-b[i])<=m)
					dp[i][0]=(dp[i][0]+dp[i-1][0])%mod;
				if(b[i]+b[i-1]==tot)
						dp[i][0]=(dp[i][0]+dp[i-1][1])%mod;
			}
			if(checkP(i)){
				int mx=b[i]+b[i-1]-tot;
				mx=mx/2+mx%2;
				if(abs(mx)<=m) dp[i][1]=(dp[i][1]+dp[i-1][0])%mod;
				if(abs(b[i]-b[i-1])<=m)
					dp[i][1]=(dp[i][1]+dp[i-1][1])%mod;
			}
			if(s[i]=='S') dp[i][1]=0;
			if(s[i]=='P') dp[i][0]=0;
		}
		ans=(ans+dp[n+1][0])%mod;
	}
	cout<<ans<<endl;
}

标签:PS,le,return,int,CodeForces,tot,1984F
From: https://www.cnblogs.com/smilemask/p/18297982

相关文章

  • Codeforces Round 957 (Div. 3)
    E-Novice'sMistake题意为寻找n*a-b=("n"+"n"+...){a个n的字符串-b的长度}即为"2"⋅20−18="22222222222222222222"−18=22=2⋅20−18使用暴力枚举每个n相加的长度和又因为n<=100a<=100000所有答案t的值必定小于1e6所以对每个a进行枚举对于每个答案t进行判断是否成立其......
  • CodeForces - 1987F1 & CodeForces - 1987F2
    分析首先显然有dp状态\(g_i\)表示前\(i\)个数,能进行最大的操作次数。转移有\(g_i=\max\limits_{j=1}^{i-1}(g_j+\frac{i-j}{2})[2|(i-j)]\)但这里显然缺少转移条件。经过基本观察,发现若\(i\)操作过,满足条件:\(a_i\equivi(mod\2)\)\(i\)左侧操作过\(\frac{i-......
  • Codeforces Round 957 (Div. 3)
    推荐个C++编程仓库模板https://github.com/yxc-s/programming-templateA.OnlyPluses总结:为什么优先增加最小的数,它们的乘积会是最优的呢?可以这么理解,假如只有两个数a和b,b>a,那么a+1,就增加一份b。如果b+1,只能增加1份a。因为b>a,所以增加小的数是最优的。voidsolve(){......
  • Codeforces Round #956 (Div. 2)题解
    A.ArrayDivisibility需要让满足$k\midj$的所有\(a_j\)的和整除k,只需要让每个\(a_j\)整除k就可以了,可以让\(a_j=j\)#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#defineendl'\n'typedefpair<int,int>pii;typedefunsignedlonglo......
  • CodeForces - 1986G1 & CodeForces - 1986G2
    经过基本观察,可得当点对\((i,j)\)合法时,有\(a_i|b_j,a_j|b_i\),其中\(a_i=i/gcd(p_i,i),b_i=p_i/gcd(p_i,i)\),证明显然。如何维护?考虑开\(mp_{x,y}\)表示\(x=a_i\),\(y|b_i\)的个数。对于点\(i\)点对个数即为\(\sum\limits_{d|b_i}mp_{d,a_i}\)时间复杂度为\(O(nlog......
  • CodeForces - 1984E
    题目大意每次在每个联通块中选一个点\(u\),删除这个点使得联通块分成若干个联通块,再从联通块中选点\(v\),在新树上连接\(u,v\),求新树叶节点的最大个数。分析易转化为求原树的最大独立集,设\(f_{u,0/1}\)为以1为根时不选/选\(u\)的最大独立集。显然有:\[dp_{u,0}=\sum\li......
  • 高考后第一次Codeforces Round 952 (Div. 4)
    ACreatingWords思路:拿一个容器交换两数值即可#include<bits/stdc++.h>usingnamespacestd;constintN=100001;chara[N],b[N];intmain(){intn;scanf("%d",&n);while(n--){scanf("%s%s",a,b);charjia......
  • Codeforces Round 954(Div. 3)
    CodeforcesRound954(Div.3)目录CodeforcesRound954(Div.3)\(C\).UpdateQueries\(D\).MathematicalProblem\(E\).BeautifulArray方法一:贪心+滑动窗口方法二:DP\(C\).UpdateQueries对索引数组\(ind\)去重排序对字符串\(c\)排序顺序遍历索引数组,将\(s[ind[i]......
  • Codeforces Round 916 (Div. 3)
    A.ProblemsolvingLog签到题,对于给出的字符串,记录每个字母出现的次数,然后遍历一遍,如果对应的字母出现的次数大于它的位次,则说明该题被解出来了,最后输出解题数量即可点击查看代码#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<vector>#......
  • Codeforces Round 956 (Div. 2) 部分题解A~C
    A.ArrayDivisibility题目大意构造长度为n的数组,满足:所有j的aj之和可以被k整除,其中j是k的倍数,k的取值为1~n。思路构造序列1->n即可满足条件。代码实现voidsolve(){  lln;cin>>n;  for(inti=1;i<=n;i++)cout<<i<<"";  cout<<"\n"......