zoukankan      html  css  js  c++  java
  • ZOJ 3494 (AC自动机+高精度数位DP)

    题目链接:  http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3494

    题目大意:给定一些被禁止的BCD码。问指定范围内不含有任何这些禁止的BCD码的数的个数。

    解题思路

    AC自动机部分:

    首先insert这些被禁止的BCD码。

    然后打一下自动机前后状态的转移的表,用BCD[i][j]表示自动机状态i时,下一个数字是j的自动机的下一个状态。

    一开始我考虑最先dfs的位在自动机的位置,后来发现SB了。AC自动机有一个root状态,也就是自动机位置为0的状态,使用这个0就行了。

    即f函数中dfs(len,0,true,true),每次由root状态出发,无须再考虑其它的。

     

    数位DP部分:

    本题的范围是高精度范围,所以需要特有的高精度写法。

    麻烦的在于f(l-1),要为高精度手艹一个-1,有种偷懒的写法,不过会导致出现前导0。

    所以在传统的dfs中需要增加一个前导0的判断。

    方法是:追加一个bool z,

    在原有的0~9基础上,单独考虑0,

    if(z) 则单独dfs前导0

    否则dfs正常的0,1~9照常dfs。当然还需要判断当前状态s的下一个状态BCD[s][i]是否符合要求。

    然后最后就是注意一下负数mod。

     

    #include "cstdio"
    #include "cstring"
    #include "queue"
    #include "iostream"
    using namespace std;
    #define maxp 25*105
    #define mod 1000000009
    struct Trie
    {
        Trie *next[2],*fail;
        int cnt;
    }pool[maxp],*root,*sz;
    int BCD[maxp][10],digit[205],ccnt;
    long long dp[205][maxp];
    Trie *newnode()
    {
        Trie *ret=sz++;
        memset(ret->next,0,sizeof(ret->next));
        ret->fail=0;
        ret->cnt=0;
        return ret;
    }
    void init()
    {
        sz=pool;
        root=newnode();
    }
    void Insert(string str)
    {
        Trie *pos=root;
        for(int i=0;i<str.size();i++)
        {
            int c=str[i]-'0';
            if(!pos->next[c]) pos->next[c]=newnode();
            pos=pos->next[c];
        }
        pos->cnt++;
    }
    void getfail()
    {
        queue<Trie *> Q;
        for(int c=0;c<2;c++)
        {
            if(root->next[c])
            {
                root->next[c]->fail=root;
                Q.push(root->next[c]);
            }
            else root->next[c]=root;
        }
        while(!Q.empty())
        {
            Trie *x=Q.front();Q.pop();
            for(int c=0;c<2;c++)
            {
                if(x->next[c])
                {
                    x->next[c]->fail=x->fail->next[c];
                    x->next[c]->cnt+=x->fail->next[c]->cnt;
                    Q.push(x->next[c]);
                }
                else x->next[c]=x->fail->next[c];
            }
        }
    }
    int judge(int status,int num)
    {
        Trie *pos=pool+status;
        if(pos->cnt) return -1;
        for(int i=3;i>=0;i--)
        {
            if(pos->next[(num>>i)&1]->cnt) return -1;
            else pos=pos->next[(num>>i)&1];
        }
        return pos-pool;
    }
    void getbcd()
    {
        for(int i=0;i<ccnt;i++)
            for(int j=0;j<10;j++)
                BCD[i][j]=judge(i,j);
    }
    int dfs(int len,int s,bool fp,bool z)
    {
        if(!len) return 1;
        if(!fp&&dp[len][s]!=-1) return dp[len][s];
        long long ret=0;
        int fpmax=fp?digit[len]:9;
        if(z)
        {
            ret+=dfs(len-1,s,fp&&digit[len]==0,true);
            ret%=mod;
        }
        else
        {
            if(BCD[s][0]!=-1) ret+=dfs(len-1,BCD[s][0],fp&&digit[len]==0,false);
            ret%=mod;
        }
        for(int i=1;i<=fpmax;i++)
        {
            if(BCD[s][i]!=-1) ret+=dfs(len-1,BCD[s][i],fp&&i==fpmax,false);
            ret%=mod;
        }
        if(!fp&&!z) dp[len][s]=ret;
        return ret;
    }
    int f(string str)
    {
        int len=0;
        for(int i=str.size()-1;i>=0;i--)
            digit[++len]=str[i]-'0';
        return dfs(len,0,true,true);
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        ios::sync_with_stdio(false);
        int T,n;
        string tt;
        cin>>T;
        while(T--)
        {
            init();
            memset(dp,-1,sizeof(dp));
            cin>>n;
            for(int i=1;i<=n;i++)
            {
                cin>>tt;
                Insert(tt);
            }
            getfail();
            ccnt=sz-pool;
            getbcd();
            cin>>tt;
            for(int i=tt.size()-1;i>=0;i--)
            {
                if(tt[i]>'0') {tt[i]--;break;}
                else {tt[i]='9';}
            }
            long long ans=0;
            ans-=f(tt);
            ans%=mod;
            cin>>tt;
            ans+=f(tt);
            ans=(ans%mod+mod)%mod;
            printf("%lld
    ",ans);
        }
    }
    2842327 neopenx ZOJ 3494 Accepted 4656 KB 210 ms C++ (g++ 4.4.5) 2976 B 2014-10-13 17:06:35

     

     

     

  • 相关阅读:
    ingress-nginx-controller 504 gateway time-out 问题
    ansible的shell模板使用awk包含引号的问题
    Python selenium模块报错解决
    redis密码破解(multiprocessing的Pool多进程模式)-join方法小坑
    redis密码破解(Python使用multiprocessing分布式进程)
    redis密码破解(python使用redis模块)
    redis密码破解(python使用socket模块)
    修改云主机快照方式为live snapshot
    虚拟机重启错误,libvirtError:internal error:process exited while connecting to monitor
    如何解决高并发秒杀的超卖问题
  • 原文地址:https://www.cnblogs.com/neopenx/p/4022659.html
Copyright © 2011-2022 走看看