其他分享
首页 > 其他分享> > AT4108 [ARC094D] Normalization

AT4108 [ARC094D] Normalization

作者:互联网

题面传送门
盲猜了个结论然后居然对了。
如果我们把a看成\(0\),b看成\(1\),c看成\(2\),容易发现一次变换后所有值加和\(\mod 3\)的值不变。
然后稍微想一想就可以发现除了\(T=S\)之外,\(T\)中一定至少一个相邻两字符相同。
所以这个是必要条件。
然后我猜这是个充分条件。
所以基础dp即可。
code:

#include <vector>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<set>
#include<map>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define l(x) x<<1
#define r(x) x<<1|1
#define re register
#define ll long long
#define db long double
#define N 200000
#define eps (1e-14)
#define mod 998244353
using namespace std;
int n,ans,tot,flag=1;ll f[N+5][3][3],g[N+5][3];char c[N+5];string s;map<string,int> fl;
I void dfs(){
	if(fl[s]) return;fl[s]=1;ans++;int i;char c;
	for(i=0;i<n-1;i++){
		if(s[i]!=s[i+1]) c=s[i],s[i]=s[i+1]=s[i]^s[i+1],dfs(),s[i]=c,s[i+1]^=s[i];
	} 
}
int main(){
	freopen("fiveopen.in","r",stdin);freopen("fiveopen.out","w",stdout);
	re int i,j,h,k;scanf("%s",c+1);n=strlen(c+1);
	if(n<=3){
		for(i=1;i<=n;i++) s+=c[i]-'a'+1;dfs();printf("%d\n",ans);
		return 0;
	}
	for(i=1;i<=n;i++) c[i]-='a',ans+=c[i];ans%=3;f[1][1][1]=f[1][0][0]=f[1][2][2]=1;
	for(i=1;i<n;i++) if(c[i]^c[i+1]){flag=0;break;} if(flag){printf("1\n");return 0;}
	for(i=1;i<=n;i++){
		for(j=0;j<=2;j++){
			for(h=0;h<=2;h++){
				g[i][j]+=g[i-1][(j-h+3)%3]+f[i-1][(j-h+3)%3][h];
				for(k=0;k<=2;k++) k^h&&(f[i][j][h]+=f[i-1][(j-h+3)%3][k]);f[i][j][h]%=mod;
			}
			g[i][j]%=mod;
		}
	}
	for(flag=1,i=1;i<n;i++)if(c[i]==c[i+1]) flag=0;printf("%lld\n",(flag+g[n][ans])%mod); 
}

标签:code,AT4108,然后,看成,Normalization,include,fl,ARC094D,define
来源: https://www.cnblogs.com/275307894a/p/14825275.html