zoukankan      html  css  js  c++  java
  • [atARC094F]Normalization

    考虑$s$能变成$t$的必要条件(假设$s e t$):

    1.$s$中存在一对相邻字符不同

    2.$|s|=|t|$且若将a-c对应为0-2,则字符模3同余;

    3.$t$中存在一对相邻两个字符相同

    同时,对于$|s|ge 4$,这个充分条件也是必要条件,证明如下:

    归纳,对于$|s|=4$暴力验证,否则考虑通过若干次操作将$s$首或尾的字符与$t$相同,然后删去这个字符

    具体的构造:若初始相同,直接删去即可,否则强制$s_{2}=s_{3}=除去s_{1}和t_{1}的另一种字符$,然后通过$s_{4}$调整模数相等,再令$s_{5}=...=s_{|s|}=a$即可,先将$s[2,|s|]$变为该字符串,然后再操作一次即相同

    同时为了保证第2个性质,若仅在首部出现相邻的相同字符,选择删去尾部,且由于$|s|ge 4$,首尾相同的部分必然不会重复,因此合法

    对于第一个条件直接判定(注意还有$s=t$的1种)即可,否则令$f[i][j][k][p]$表示$t$中前$i$个字符和模3为$j$,最后一个字符为$k$,是否出现过相邻字符相同的方案数,转移分类讨论即可

    特别的,如果$s$中没有相邻两个字符,但$t=s$仍然是合法解,答案要加1

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 200005
     4 #define mod 998244353
     5 int n,sum,ans,vis[3][3][3],f[N][3][3][2];
     6 char s[N];
     7 void dfs(int a,int b,int c){
     8     if (vis[a][b][c])return;
     9     vis[a][b][c]=1;
    10     ans++;
    11     if (a!=b)dfs(3-a-b,3-a-b,c);
    12     if (b!=c)dfs(a,3-b-c,3-b-c);
    13 }
    14 int main(){
    15     scanf("%s",s);
    16     n=strlen(s);
    17     if (n==2){
    18         printf("%d",1+(s[0]!=s[1]));
    19         return 0;
    20     }
    21     if (n==3){
    22         dfs(s[0]-'a',s[1]-'a',s[2]-'a');
    23         printf("%d",ans);
    24         return 0;
    25     }
    26     bool flag=0;
    27     for(int i=1;i<n;i++)
    28         if (s[i]!=s[0]){
    29             flag=1;
    30             break;
    31         }
    32     if (!flag){
    33         printf("1");
    34         return 0;
    35     }
    36     for(int i=0;i<3;i++)f[0][i][i][0]=1;
    37     for(int i=1;i<n;i++)
    38         for(int j=0;j<3;j++)
    39             for(int k=0;k<3;k++)
    40                 for(int l=0;l<3;l++)
    41                     for(int p=0;p<2;p++)
    42                         f[i][j][k][(p|(l==k))]=(f[i][j][k][(p|(l==k))]+f[i-1][(j+3-k)%3][l][p])%mod;
    43     sum=0,ans=1;
    44     for(int i=0;i<n;i++)sum=(sum+s[i]-'a')%3;
    45     for(int i=1;i<n;i++)ans&=(s[i]!=s[i-1]);
    46     for(int i=0;i<3;i++)ans=(ans+f[n-1][sum][i][1])%mod;
    47     printf("%d",ans);
    48 }
    View Code
  • 相关阅读:
    安卓系统源码编译系列(六)——单独编译内置浏览器WebView教程
    android4.0浏览器在eclipse中编译的步骤
    android.net.wifi的简单使用方法
    android:sharedUserId 获取系统权限
    android 常见死机问题--log分析
    android anr分析方法
    android的logcat详细用法
    Android 设计模式 之 观察者模式
    Android 设计模式 之 单例模式
    android 自定义控件 使用declare-styleable进行配置属性(源码角度)
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14057259.html
Copyright © 2011-2022 走看看