zoukankan      html  css  js  c++  java
  • P3311 [SDOI2014] 数数

    P3311 [SDOI2014] 数数

    感觉我太不自信了,其实思路都是对的,就是不敢写,想到了也不写。

    这题综合了一些东西。

    首先非常套路对于所有模式串建AC自动机,维护出 (Trie) 图上哪些点不能到达

    如何限制 (le n) ?这就很像数位dp了,dp状态多一维 (0/1) 表示是否顶到上界

    我开心地写完了这个dp却发现WA40

    到讨论区发现被下面那组hack了

    2000
    1
    001
    

    很明显是前导零的问题,但是我怀疑是别的问题懒得改。最后就是这个问题。

    如果还有前导零那么当前点设为 (0) ,否则走 (Trie) 图上的出边。

    干脆换成记搜写数位dp了

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef double db;
    #define x first
    #define y second
    #define sz(v) (int)v.size()
    #define pb(x) push_back(x)
    #define mkp(x,y) make_pair(x,y)
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=0;c=getchar();}
    	while(isdigit(c))x=x*10+c-'0',c=getchar();
    	return f?x:-x;
    }
    #define mod 1000000007
    #define N 1505
    char n[N];
    int m,Len,ch[N][10],tot,dp[N][N][2][2],fail[N];
    bool en[N];
    void fmod(int&x){x-=mod,x+=x>>31&mod;}
    void insert(char*str){
    	int u=0,len=strlen(str);
    	for(int i=0;i<len;++i){
    		int c=str[i]-'0';
    		if(!ch[u][c])ch[u][c]=++tot;
    		u=ch[u][c];
    	}
    	en[u]=1;
    }
    void build_fail(){
    	queue<int>q;
    	for(int i=0;i<10;++i)if(ch[0][i])q.push(ch[0][i]);
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		en[u]|=en[fail[u]];
    		for(int i=0;i<10;++i)
    			if(ch[u][i])fail[ch[u][i]]=ch[fail[u]][i],q.push(ch[u][i]);
    			else ch[u][i]=ch[fail[u]][i];
    	}
    }
    int dfs(int u,int pos,int limit,int lead){
    	if(!pos)return !en[u];
    	if(en[u])return 0;
    	if(~dp[u][pos][limit][lead])return dp[u][pos][limit][lead];
    	int up=limit?n[pos-1]-'0':9,res=0;
    	for(int i=0;i<=up;++i)fmod(res+=dfs(lead&&!i?0:ch[u][i],pos-1,limit&&i==up,lead&&!i));
    	return dp[u][pos][limit][lead]=res;
    }
    signed main(){
    	scanf("%s%d",n,&m),Len=strlen(n);
    	for(int i=1;i<=m;++i){
    		static char str[N];
    		scanf("%s",str),insert(str);
    	}
    	build_fail();
    	reverse(n,n+Len);
    	memset(dp,-1,sizeof(dp));
    	printf("%d
    ",(dfs(0,Len,1,1)+mod-1)%mod);
    	return 0;
    }
    
  • 相关阅读:
    (转)Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks(更快的RCNN:通过区域提议网络实现实时)
    vi常用命令
    Windows与Ubuntu通过ssh传文件
    Windows建立FTP服务器与Ubuntu互传文件
    备忘
    一些大牛博客地址
    springboot、springcloud学习记录
    我的git记录
    svn
    我的linux命令记录
  • 原文地址:https://www.cnblogs.com/zzctommy/p/13892028.html
Copyright © 2011-2022 走看看