zoukankan      html  css  js  c++  java
  • [atAGC055D]ABC Ultimatum

    记$f_{k}$为$\max_{0\le i\le 3n}\sum_{j=1}^{i}([s_{j}=next(k)]-[s_{j}=k])$(其中$k\in \{a,b,c\},next(a/b/c)=b/c/a$)

    结论:有解当且仅当$\sum_{k\in \{a,b,c\}}f_{k}\le n$

    必要性:对于合法的子序列,都包含两个形如$(k,next_{k})$的顺序对(每一个字符最多使用一次)

    而考虑$f_{a}$,即意味着$(a,b)$这样的顺序对至多只会出现$n-f(a)$次(在$i$之前的多出的$b$一定无法使用),而总共要有$2n$个,代入后也即$\sum_{k\in \{a,b,c\}}f_{k}\le n$

    充分性:将第$i$个a、第$i+f_{a}$个b和第$i+f_{a}+f_{b}$个c组成一个子序列(后两者若大于$n$再减去$n$)

    性质:$\forall k\in \{a,b,c\},i+f_{k}\le n$,第$i$个$k$总是在第$i+f_{k}$个$next(k)$之前

    考虑第$i$个$k$的前缀(不包括第$i$个$k$),其中有$i+f_{k}$个$next(k)$和$i-1$个$k$,与$f_{k}$最大性矛盾

    由此,对$i$分类讨论,来证明$i$时的子序列合法:

    1.若$i+f_{a}+f_{b}\le n$,由性质显然这是一个形如abc的子序列

    2.若$i+f_{a}\le n<i+f_{a}+f_{b}$,后者结合条件即$i>f_{c}$且$i+f_{a}+f_{b}-n<i-f_{c}$,由性质显然这是一个形如cab的子序列

    3.若$n<i+f_{a}$,类似地上述两种情况,也可以证明这是一个形如bca的子序列

    综上,即得证

    由此,对每一个$k$的当前前缀和和最大前缀和(即$f_{k}$)一起dp即可,时间复杂度为$o(n^{7})$

    另一方面,注意到当前前缀和之和必然为0,即可优化到$o(n^{6})$

    总复杂度为$o(n^{6})$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 16
     4 #define mod 998244353
     5 int n,l,ans,f[N*3][N*2][N*2][N][N][N];
     6 char s[N*3];
     7 void Add(int &x,int y){
     8     x=(x+y<mod ? x+y : x+y-mod);
     9 }
    10 int main(){
    11     scanf("%d%s",&n,s),l=n*3;
    12     f[0][n][n][0][0][0]=1;
    13     for(int i=0;i<l;i++)
    14         for(int sa=-n;sa<=n;sa++)
    15             for(int sb=-n;sb<=n;sb++){
    16                 int sc=-sa-sb;
    17                 if (abs(sc)>n)continue;
    18                 for(int fa=0;fa<=n;fa++)
    19                     for(int fb=0;fb<=n;fb++)
    20                         for(int fc=0;fc<=n;fc++){
    21                             if (((s[i]=='A')||(s[i]=='?'))&&(sa>-n))
    22                                 Add(f[i+1][sa+n-1][sb+n][fa][fb][max(fc,sc+1)],f[i][sa+n][sb+n][fa][fb][fc]);
    23                             if (((s[i]=='B')||(s[i]=='?'))&&(sb>-n))
    24                                 Add(f[i+1][sa+n+1][sb+n-1][max(fa,sa+1)][fb][fc],f[i][sa+n][sb+n][fa][fb][fc]);
    25                             if (((s[i]=='C')||(s[i]=='?'))&&(sc>-n))
    26                                 Add(f[i+1][sa+n][sb+n+1][fa][max(fb,sb+1)][fc],f[i][sa+n][sb+n][fa][fb][fc]);
    27                         }
    28             }
    29     for(int fa=0;fa<=n;fa++)
    30         for(int fb=0;fb<=n;fb++)
    31             for(int fc=0;fc<=n;fc++)
    32                 if (fa+fb+fc<=n)Add(ans,f[l][n][n][fa][fb][fc]);
    33     printf("%d\n",ans);
    34     return 0;
    35 }
    View Code
  • 相关阅读:
    总结7.19 laravel验证码
    java学习day74--Redis常用命令
    java学习day74--JT项目12(Redis缓存/spring boot整合redis)
    java学习day73-JT项目11(数据库高可用/读写分离/负载均衡)
    疯狂学java的第27天
    xtrabackup全备+binlog模拟slave恢复到某一时间点-启用GTID
    读写文件
    goroutine、chan、select、互斥、读写互斥
    接口

  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/15628822.html
Copyright © 2011-2022 走看看