zoukankan      html  css  js  c++  java
  • [Wannafly冬令营2018Day3] 小游戏

    link

    题意简述

    初始有 $n$ 个小球,小球有 $4$ 种颜色,初始的等级为 $0$

    你每一次可以选择一个小球删除,删除后后面的小球会向前 移动一位 

    如果有至少 $3$ 个相同颜色和等级的小球连续,那么左侧的 $3$ 个会合并成一个颜色相同等级 $+1$ 的小球(可能有连锁反应)

    问有多少种能到达的局面 两个局面是不同当且仅当长度不同或存在一个位置小球不同

    $nleq 10^6$ 。

    题目解析

    去考虑如何判断一种情况是否存在,比如是否在 $AABABBAB$ 中存在 $A(1)B(1)$ ,可以简单贪心找最近符合要求的球。

    设 $f_{i,j,k}$ 表示在 $1-i$ 中最后一个球等级为 $j$ 且有连续 $k$ 个,每次通过倍增处理出下次最近符合条件的位置。

    但是 $AABAA$ 在上述算法中看成 $A(1)A(0)$,$A(0)A(1)$ ,但是 $A(1)A(0)$ 却并不能构成,因为是有 $>3$ 个同色球相同的时候是向左合并的 。

    而形成这种条件的是 $s_i=s_{i+1}$,考虑这种情况在 $i$ 转移时会发生的情况,若前面产生 $A(x)$ ,则后面产生 $B,C,D$ 不会形成,而只有产生 $A(y)$ 且 $(x<y)$ 时会有一定影响、

    如果 $i+1$ 要被使用的话必须 $x<y$ ,而 $i+1$ 不被使用的话可以产生 $A(x)A(y),x<y$ ,因为可以通过 $i+2$ 的不同颜色区分。

    时间复杂度 $O(nlog^2n)$,可以通过简单优化实现 $O(nlog n)$ 。

    貌似就是个本质不同子序列计数。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define int long long
    #define mod 998244353
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return ans*f;
    }
    const int MAXN=1000011;
    int f[MAXN][13][2],len;char str[MAXN];
    int now[4],nex[MAXN][4][13],Ans;
    signed main(){
    //    freopen("1.in","r",stdin);
        len=read();scanf("%s",str+1);
        for(int i=0;i<=12;i++) for(int j=0;j<=3;j++) nex[len+1][j][i]=len+1;
        for(int j=0;j<=3;j++) now[j]=len+1;
        for(int i=len;i>=0;i--){
            for(int j=0;j<=3;j++) nex[i][j][0]=now[j];
            now[str[i]-'A']=i;
        }
        for(int i=1;i<=12;i++) for(int j=0;j<=len;j++) for(int k=0;k<=3;k++) nex[j][k][i]=nex[nex[nex[j][k][i-1]][k][i-1]][k][i-1];
        for(int i=0;i<=len;i++){
            if(i!=len&&str[i]==str[i+1]){
                for(int j=0;j<=12;j++){
                    int p=nex[i+1][str[i]-'A'][j];
                    for(int k=0;k<j;k++) f[p][j][0]+=f[i][k][0]+f[i][k][1],f[p][j][0]%=mod;
                }
            }
            for(int j=0;j<=12;j++){
                for(int k=0;k<4;k++){
                    int p=nex[i][k][j];if(p==len+1) continue;
                    if(i==0) f[p][j][0]+=1;
                    for(int z=0;z<12;z++){
                        if(str[i]-'A'==k&&j==z) f[p][j][1]+=f[i][z][0],f[p][j][1]%=mod;
                        else if(str[i]-'A'==k&&str[i]==str[i+1]&&z<j) continue;
                        else f[p][j][0]+=f[i][z][0]+f[i][z][1],f[p][j][0]%=mod;
                    }
                }Ans+=f[i][j][0]+f[i][j][1],Ans%=mod;
            }
        }printf("%lld
    ",Ans);return 0;
    }/*
    3
    ABA
    */
    View Code
  • 相关阅读:
    WIndows下编译libexif-0.6.21,生成VS下可用的dll和lib
    Android开发之获取系统12/24小时制的时间
    转自 x_x的百度空间
    BZOJ1483: [HNOI2009]梦幻布丁
    BZOJ2124: 等差子序列
    BZOJ2431: [HAOI2009]逆序对数列
    BZOJ1831: [AHOI2008]逆序对
    2821: 作诗(Poetize)
    BZOJ2038小Z的袜子(hose)
    NOI2005维护数列
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/12316580.html
Copyright © 2011-2022 走看看