zoukankan      html  css  js  c++  java
  • SDOI2014 数数

    题目描述:

    我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串。

    例如当S=(22,333,0233)时,233是幸运数,2333、20233、3223不是幸运数。

    给定N和S,计算不大于N的幸运数个数。

     题解:
    trie图上数位dp。

    好像很裸的样子。

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MOD 1000000007
    char lim[1250],s[1505];
    int m,tot;
    struct Trie
    {
        int ch[12],fl,w;
    }tr[1505];
    void trie_pic()
    {
        queue<int>q;
        for(int i=0;i<=9;i++)
            if(tr[0].ch[i])
                q.push(tr[0].ch[i]);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            for(int i=0;i<=9;i++)
            {
                int &v = tr[u].ch[i];
                if(!v)
                {
                    v=tr[tr[u].fl].ch[i];
                    continue;
                }
                tr[v].fl=tr[tr[u].fl].ch[i];
                tr[v].w|=tr[tr[v].fl].w;
                q.push(v);
            }
        }
    }
    int dp[2][1205][1505],ans;//0 边界以内 1 边界上 
    int main()
    {
        scanf("%s%d",lim+1,&m);
        int lm = strlen(lim+1);
        for(int i=1;i<=m;i++)
        {
            scanf("%s",s+1);
            int u=0,len=strlen(s+1);
            for(int j=1;j<=len;j++)
            {
                int c = s[j]-'0';
                if(!tr[u].ch[c])tr[u].ch[c]=++tot;
                u=tr[u].ch[c];
            }
            tr[u].w=1;
        }
        trie_pic();
        for(int i=0;i<lm;i++)
        {
            for(int j=0;j<=tot;j++)
            {
                if(dp[0][i][j])
                {
                    for(int k=0;k<=9;k++)
                    {
                        int to = tr[j].ch[k];
                        if(tr[to].w)continue;
                        (dp[0][i+1][to]+=dp[0][i][j])%=MOD;
                    }
                }
                if(dp[1][i][j])
                {
                    for(int k=0;k<lim[i+1]-'0';k++)
                    {
                        int to = tr[j].ch[k];
                        if(tr[to].w)continue;
                        (dp[0][i+1][to]+=dp[1][i][j])%=MOD;
                    }
                    int to = tr[j].ch[lim[i+1]-'0'];
                    if(!tr[to].w)(dp[1][i+1][to]+=dp[1][i][j])%=MOD;
                }
                if(!j)
                {
                    if(!i)
                    {
                        for(int k=1;k<lim[1]-'0';k++)
                        {
                            int to = tr[j].ch[k];
                            if(tr[to].w)continue;
                            (dp[0][i+1][to]+=1)%=MOD;
                        }
                        int to = tr[j].ch[lim[1]-'0'];
                        if(!tr[to].w)(dp[1][i+1][to]+=1)%=MOD;
                    }else
                    {
                        for(int k=1;k<=9;k++)
                        {
                            int to = tr[j].ch[k];
                            if(tr[to].w)continue;
                            (dp[0][i+1][to]+=1)%=MOD;
                        }
                    }
                }
            }
        }
        int ans = 0;
        for(int i=0;i<=tot;i++)
        {
            (ans+=(dp[0][lm][i]+dp[1][lm][i])%MOD)%=MOD;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    剑指Offer(书):重建二叉树
    剑指Offer(书):从尾到头打印链表
    剑指Offer(书):替换空格
    剑指Offer(书):二维数组中的查找
    剑指Offer(书):数组中重复的数字
    剑指Offer(书):实现单例模式
    Centos 7安装Mysql5.7
    3000客接口迁移一记
    安装完Centos 7后的一些处理
    算法笔记—入门篇(2)—算法初步(更新中......)
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10046117.html
Copyright © 2011-2022 走看看