• [cf461E]Appleman and a Game


    考虑我的每一次添加操作,要满足:1.该串是t的子串;2.该串不能与下一次的串开头字母构成t的子串。那么,设f[i][j][k]表示拼i次,第i次填入的开头字母是j,第i+1填入的开头字母是k的最短长度。

    状态转移方程:f[i][j][k]=min(f[i-1][j][t]+f[1][t][k]),这个东西可以用矩阵乘法来搞(把加改成min即可)。

    这样求出的最后一个存在jk满足f[i][j][k]<ni即为答案,因为f[i][j][k]的值一定随i的增长而增长,因此可以二分i并判断是否存在。

    之后还要预处理出f[1][i][j],这个东西暴力枚举显然是$o(n^{2})$的,但是发现判断f[1][i][j]不合法当且仅当所有以i为开头以j为结尾且长度为f[1][i][j]的串都是t的子串,而t中长度固定的串不超过|t|个,而这样的串有$4^{f[1][i][j]}$个,如果满足$4^{f[1][i][j]}>|t|$f[1][i][j]一定不合法,大约有$f[1][i][j]\leq 20$

    接下来计算就很简单来,可以对s中所有长度小于等于20的子串建一棵trie树并统计一下就可以。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 struct ji{
     5     ll a[5][5];
     6 }a,b,c;
     7 ll n,k;
     8 int V,tr[2000005][5],f[5][5][100005];
     9 char s[100005];
    10 void ins(int k){
    11     for(int i=k,j=1;(i<k+20)&&(s[i]);j=tr[j][s[i++]-'A'])
    12         if (!tr[j][s[i]-'A']){
    13             tr[j][s[i]-'A']=++V;
    14             f[s[k]-'A'][s[i]-'A'][i-k]++;
    15         }
    16 }
    17 ji cheng(ji a,ji b){
    18     for(int i=0;i<4;i++)
    19         for(int j=0;j<4;j++)c.a[i][j]=n+1;
    20     for(int i=0;i<4;i++)
    21         for(int j=0;j<4;j++)
    22             for(int k=0;k<4;k++)
    23                 c.a[i][k]=min(c.a[i][k],a.a[i][j]+b.a[j][k]);
    24     return c;
    25 }
    26 void ksm(ji a,ll n){
    27     while (n){
    28         if (n&1)b=cheng(b,a);
    29         a=cheng(a,a);
    30         n/=2;
    31     }
    32 }
    33 bool pd(ji a){
    34     for(int i=0;i<4;i++)
    35         for(int j=0;j<4;j++)
    36             if (a.a[i][j]<n)return 1;
    37     return 0;
    38 }
    39 int main(){
    40     scanf("%lld%s",&n,s);
    41     V=1;
    42     for(int i=0;s[i];i++)ins(i);
    43     for(int i=0;i<4;i++)
    44         for(int j=0;j<4;j++){
    45             for(int k=1;f[i][j][k]==(1<<(2*k-2));k++)a.a[i][j]=k;
    46             a.a[i][j]++;
    47         }
    48     k=n;
    49     for(ll i=0;i<k;){
    50         memset(b.a,0,sizeof(b.a));
    51         ll j=(i+k+1>>1);
    52         ksm(a,j);
    53         if (pd(b))i=j;
    54         else k=j-1;
    55     }
    56     printf("%lld",k+1);
    57 }
    View Code
  • 相关阅读:
    如何将应用安装到/system/app下
    WPF Perf: RenderCapability.Tier & DesiredFrameRate
    DataGridComboBoxColumn为什么就不能在Binding的时候引用其他Named Element了呢?
    A366T使用技巧
    在XAML里面引用枚举值的注意点
    高斯消元bzoj1013球形空间产生器
    欧拉函数bzoj2818简单推导
    链剖进阶ing填坑NOIP2013货车运输
    .net 2.0 BackgroundWorker 文章三篇
    19号晚21号上午
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11254592.html
Copyright © 2020-2023  润新知