首页 > 其他分享 >1111

1111

时间:2022-11-11 18:33:19浏览次数:48  
标签:状态 相等 int 1111 回文 dp mod

总结一下最近做的一些题目

模拟赛20221110 猪尾巴 | CQNK

这个题很明显是一个压状态然后dp的题,场上也一直在往这个方向想,但是没有做出来。

首先,最暴力的压状态方法就是把最后k位的最小表示全部压下来,然后每次确保转移到的不是回文串即可,复杂度 \(O(nBell_k)\),明显跑不了。

然后场上的想法是类似回文树一样,维护最后k位的fail集合,但是这是每一次跳fail与fail的前一位是什么字符有关,而这是难以转移的,场上经过若干次尝试,发现不可做,就只好打了最低的暴力。

然后题解的做法就十分巧妙了,这种dp的思想以前并没有见过,所以记录下来,希望以后可以变为一个常规的套路。

首先,改变计算答案的方式,之前的做法是保证0每一次最后k位都不回文,但是这样是难以实现的。于是考虑容斥,令 F(x) 为至少有x个长度为k的回文串,那么最终的答案就是 \(\sum F(i) \times-1^i\),于是在dp的时候可以把容斥系数和方案数一起算,每次可以钦定最后k位是回文的,那么容斥系数会取反。

那么现在需要设计dp的状态:每一次转移可以是最后一位随便填,或者强行钦定最后k位是回文。

如果钦定最后k为是回文的,那么就会出现k/2对相等关系(s_1=s_k,s_2=s_k-1,……),于是可以使用令dp状态为最后k位的相等关系的最小表示(如:状态:112331 表示第1、2、6位是相等的,第4、5位是相等的),注意这个状态只记录了钦定的相等关系,即:同一块内必定相等,但是不同的块不一定不相等,所有dp算的是至少出现x次回文的方案数。

然后考虑转移,这是本题第二个之处:对方案的贡献不要在一个字符进来的时候计算,因为一个字符加入状态以后可能会在之后出现一些相等关系,使它不能独立选择;所以我们在每一个块的最后一个统计答案,即如果当前的第k+1个是它的块的最后一个,那么这个块在之后肯定不会再出现,就可以在这里统计贡献。即看当前出状态的那个,如果它是独立的,计算贡献。

然后状态dfs出来发现不是很多,就可以dp了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,int b){a+=b;if(a>=mod)a-=mod;}
inline int mul(int a,int b){return (ll)a*b%mod;}
int n,k,c,ans,tot;
typedef vector<int> V;
map<vector<int>,int> mp;
int id[100];
void trans1(V &v){
	int o=0;
	vector<int> v1;
	for(int i=0;i<k;i++){
		if(!id[v[i]])id[v[i]]=++o;
		v1.push_back(id[v[i]]-1);	
	}
	for(int i=0;i<k;i++)id[v[i]]=0;
	v=v1;
}
int fa[100];
int gf(int x){return x==fa[x]?x:fa[x]=gf(fa[x]);}
void trans2(V &v){
	for(int i=0;i<k;i++)fa[i]=i;
	for(int i=0;i<k;i++){
		int x=gf(v[i]),y=gf(v[k-i-1]);
		fa[y]=x;
	}
	for(int i=0;i<k;i++)v[i]=gf(v[i]);
	trans1(v);
}
pair<int,int> to[100005][2];
int sz[100005]; 
void dfs(V v,int id){
	V v1;
	bool flag=0;
	for(int i=1;i<k;i++)v1.push_back(v[i]),flag|=v[i]==v[0],sz[id]=max(sz[id],v[i]);
	sz[id]++;
	v1.push_back(k+1);
	trans1(v1);
	int &now=mp[v1];
	if(!now){now=++tot;dfs(v1,now);}
	to[id][0]=make_pair(now,flag?1:c);
	trans2(v1);
	int &now1=mp[v1];
	if(!now1){now1=++tot;dfs(v1,now1);}
	to[id][1]=make_pair(now1,flag?mod-1:mod-c);
}
int f[2][100005],pw[100];
int main(){
	cin>>n>>k>>c;
	V v;
	for(int i=0;i<k;i++)v.push_back(i);
	mp[v]=tot=1,f[0][1]=1,f[0][2]=mod-1;
	dfs(v,1);
	int p=0;
	pw[0]=1;
	for(int i=1;i<=k;i++)pw[i]=mul(pw[i-1],c);
	for(int i=k+1;i<=n;i++,p^=1){
		for(int j=1;j<=tot;j++){
			if(!f[p][j])continue;
			Add(f[p^1][to[j][0].first],mul(f[p][j],to[j][0].second));
			Add(f[p^1][to[j][1].first],mul(f[p][j],to[j][1].second)); 
			f[p][j]=0;
		}
	}
	int ans=0;
	for(int i=1;i<=tot;i++)Add(ans,mul(f[p][i],pw[sz[i]]));
	cout<<ans<<endl;
	return 0;
}

标签:状态,相等,int,1111,回文,dp,mod
From: https://www.cnblogs.com/william555/p/16881425.html

相关文章

  • 20221111_T1B_线段树优化建图/并查集
    题意给定一个字符串,其中只有a和b,现在一个字符能够跳到与之中间a的个数范围在\([l,r]\)的东西。题解赛时得分:100/100对于一个东西,显然如果将能相互到达连边,那么......
  • C# =>实用详解(20221111)
    =>主要有两方面的作用,一个限制属性状态,另一个简化匿名委托和Lambda用法一:定义只读属性 publicclassManPeople{publicstringSex=>"男"; publicstringNam......
  • 1. 演进、环境与资源-20221111
    C++11也叫2.0了解:之前std:tr1的内容都已经放到std内了搜索:   :Gcc:unix家族,MinGW:windows家族   选择支持C++11还是14:【右击项目】–【选择属性】–【C/C++......
  • [A202211110354]
    [A202211110354](2022,南开大学)设\(x_n=\displaystyle\sum_{k=0}^n{\frac{1}{k!}}\),\(n=1,2,\cdots\),求极限\[\lim_{n\rightarrow\infty}\left(\frac{\lnx_n}{\sqr......
  • [A202211110303]
    [A202211110303](2022,同济大学)已知\(\{a_n\}\)是一个实数列,\(0<|\lambda|<1\).证明:\(\displaystyle\lim_{n\rightarrow\infty}a_n=a\)的充要条件是\[\lim_{n\rig......
  • 11111
    文字少的博文不允许投稿到博客园首页文字少的博文不允许投稿到博客园首页文字少的博文不允许投稿到博客园首页文字少的博文不允许投稿到博客园首页文字少的博文不允许投稿......
  • P1111 修复公路
    ​​传送门​​思路:用并查集来维护村与村之间的联通关系,类似于最小生成树中的并查集用法。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;structnode......
  • 10.3 - 1111
    compue_section_header():计算每个sectionheader的大小因为每个符号无论是出现在.data还是.test还是.rodata它都一定出现在符号解析后smap中所以我们只需要遍历smap写......
  • DFS算法练习 POJ1111; POJ1129; POJ2245; POJ2657
    POJ1111:importjava.util.Scanner;/***@Authorjinjun99*@DateCreatedin2022/9/279:49*@Description*@Sinceversion-1.0*/publicclassMain{......
  • 111111
    昨日数据回顾(自己方便记单词,别模仿)布尔值bollTrue,False意思是对的和错的所有的数据自带布尔值布尔值为Flase的有0None''[]{}元组......