zoukankan      html  css  js  c++  java
  • [bzoj3530][Sdoi2014]数数_AC自动机_数位dp

    数数 bzoj-3530 Sdoi-2014

    题目大意:给你一个整数集合,求所有不超过n的正整数,是的它的十进制表示下不能再一段等于集合中的任意数。

    注释:$1le n le 1200$,$1le |S|le 100$,$1le Lle 1500$,L是总长度之和。

    想法:咳咳,显然,我们... ...什么都不想,看着能开下先把AC自动机扔出来

    然后,其实数位dp就可以了

    具体看代码

    最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #define mod 1000000007 
    using namespace std;
    typedef long long ll;
    struct tree
    {
    	int fail;
    	int vis[11];
    	int end;
    }a[1600];
    char s[1600],t[1250];
    int n,m,cnt;
    ll f[3][1250][1600],ans;
    void build(char *s)
    {
    	int l=strlen(s);
    	int now=0;
    	for(int i=0;i<l;i++)
    	{
    		int x=s[i]-'0';
    		if(!a[now].vis[x])
    		{
    			a[now].vis[x]=++cnt;
    		}
    		now=a[now].vis[x];
    	}
    	a[now].end|=1;
    }
    queue<int>q;
    void getfail()
    {
    	while(!q.empty()) q.pop();
    	for(int i=0;i<10;i++)
    	{
    		if(a[0].vis[i]!=0)
    		{
    			a[a[0].vis[i]].fail=0;
    			q.push(a[0].vis[i]);
    		}
    	}
    	while(!q.empty())
    	{
    		int now=q.front();q.pop();
    		for(int i=0;i<10;i++)
    		{
    			if(!a[now].vis[i])
    			{
    				a[now].vis[i]=a[a[now].fail].vis[i];
    			}
    			else
    			{
    				a[a[now].vis[i]].fail=a[a[now].fail].vis[i];
    				a[a[now].vis[i]].end|=a[a[a[now].fail].vis[i]].end;
    				q.push(a[now].vis[i]);
    			}
    		}
    	}
    }
    int main()
    {
    	scanf("%s",t+1);
    	m=strlen(t+1);
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%s",s),build(s);
    	getfail();
    	for(int i=0;i<m;i++)
    	{
    		for(int j=0;j<=cnt;j++)
    		{
    			if(!j)
    			{
    				if(!i)
    				{
    					int x=t[i+1]-'0';
    					for(int k=1;k<x;k++)
    					{
    						if(!a[a[j].vis[k]].end)
    						{
    							f[1][i+1][a[j].vis[k]]+=1;
    							f[1][i+1][a[j].vis[k]]%=mod;
    						}
    					}
    					if(!a[a[j].vis[x]].end)
    					{
    						f[0][i+1][a[j].vis[x]]+=1;
    						f[0][i+1][a[j].vis[x]]%=mod;
    					}
    				}
    				else
    				{
    					for(int k=1;k<=9;k++)
    					{
    						if(!a[a[j].vis[k]].end)
    						{
    							f[1][i+1][a[j].vis[k]]++;
    							f[1][i+1][a[j].vis[k]]%=mod;
    						}
    					}
    				}
    			}
    			if(f[0][i][j])
    			{
    				int x=t[i+1]-'0';
    				for(int k=0;k<x;k++)
    				{
    					if(!a[a[j].vis[k]].end)
    					{
    						f[1][i+1][a[j].vis[k]]+=f[0][i][j];
    						f[1][i+1][a[j].vis[k]]%=mod;
    					}
    				}
    				if(!a[a[j].vis[x]].end)
    				{
    					f[0][i+1][a[j].vis[x]]+=f[0][i][j];
    					f[0][i+1][a[j].vis[x]]%=mod;
    				}
    			}
    			if(f[1][i][j])
    			{
    				for(int k=0;k<=9;k++)
    				{
    					if(!a[a[j].vis[k]].end)
    					{
    						f[1][i+1][a[j].vis[k]]+=f[1][i][j];
    						f[1][i+1][a[j].vis[k]]%=mod;
    					}
    				}
    			}
    		}
    	}
    	for(int i=0;i<=cnt;i++)
    	{
    		ans+=f[0][m][i];
    		ans%=mod;
    		ans+=f[1][m][i];
    		ans%=mod;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

     小结:我们在处理字符串问题的时候脑子里先有几个数据结构在搞事情.. ...

  • 相关阅读:
    20155222 第二周测试
    2017-2018-1 20155222 《信息安全系统设计基础》第3周学习总结
    20155222 2016-2017-2《Java程序设计》课程总结
    2016-2017-2 20155222 实验五 网络编程与安全
    20155222 2016-2017-2 《Java程序设计》实验三
    20155222 2016-2017-2 《Java程序设计》第10周学习总结
    20155222 2016-2017-2 《Java程序设计》实验二
    20155222 2016-2017-2 《Java程序设计》第9周学习总结
    2017-2018-1 20155228 《信息安全系统设计基础》第二周课堂测试与课后作业
    2017-2018-1 20155228 《信息安全系统设计基础》第一周学习总结
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9278438.html
Copyright © 2011-2022 走看看