zoukankan      html  css  js  c++  java
  • Bzoj3530: [Sdoi2014]数数

    题面

    传送门

    Sol

    在AC自动机上跑数位DP
    (f[i][j][0/1])表示到(n的第i位)当前匹配到(AC自动机的j节点)的方案
    转移就在AC自动机上跑
    注意不能有前导零,可能有这种情况(000000)不能存在那么前导零就有问题
    所以要单独把小于(n)的位数的数单独算出来,等于(n)的位数的数单独算出来最后加起来

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int Zsy(1e9 + 7), _(1510);
    
    int n, m, ch[10][_], tot, fail[_], f[3][_][_], ans;
    bool cnt[_];
    char s[_], T[_];
    queue <int> Q;
    
    IL void Insert(){
    	RG int x = 0, len = strlen(s);
    	for(RG int i = 0; i < len; ++i){
    		if(!ch[s[i] - '0'][x]) ch[s[i] - '0'][x] = ++tot;
    		x = ch[s[i] - '0'][x];
    	}
    	cnt[x] = 1;
    }
    
    IL void GetFail(){
    	for(RG int i = 0; i <= 9; ++i) if(ch[i][0]) Q.push(ch[i][0]);
    	while(!Q.empty()){
    		RG int fa = Q.front(); Q.pop();
    		for(RG int i = 0; i <= 9; ++i)
    			if(ch[i][fa]) fail[ch[i][fa]] = ch[i][fail[fa]], Q.push(ch[i][fa]);
    			else ch[i][fa] = ch[i][fail[fa]];
    		cnt[fa] |= cnt[fail[fa]];
    	}
    }
    
    IL void Calc(){
    	f[1][0][0] = f[2][0][0] = 1;
    	for(RG int i = 0; i < n; ++i)
    		for(RG int j = 0; j <= tot; ++j){
    			if(cnt[j]) continue;
    			for(RG int l = 0; l <= 9; ++l){
    				RG int p = ch[l][j];
    				if(!(i + l) || cnt[p]) continue;
    				(f[2][i + 1][p] += f[2][i][j]) %= Zsy;
    			}
    		}
    	for(RG int i = 1; i < n; ++i)
    		for(RG int j = 0; j <= tot; ++j)
    			(ans += f[2][i][j]) %= Zsy;
    	for(RG int i = 0; i < n; ++i)
    		for(RG int j = 0; j <= tot; ++j){
    			if(cnt[j]) continue;
    			for(RG int l = 0; l <= 9; ++l){
    				RG int p = ch[l][j];
    				if(!(i + l) || cnt[p]) continue;
    				(f[0][i + 1][p] += f[0][i][j]) %= Zsy;
    				if(l + '0' == T[i + 1]) (f[1][i + 1][p] += f[1][i][j] % Zsy) %= Zsy;
    				if(l + '0' < T[i + 1]) (f[0][i + 1][p] += f[1][i][j]) %= Zsy;
    			}
    		}
    }
    
    int main(RG int argc, RG char* argv[]){
    	scanf(" %s%d", T + 1, &m); n = strlen(T + 1);
    	for(RG int i = 1; i <= m; ++i) scanf(" %s", s), Insert();
    	GetFail(); Calc();
    	for(RG int i = 0; i <= tot; ++i) (ans += (f[0][n][i] + f[1][n][i]) % Zsy) %= Zsy;
    	printf("%d
    ", ans);
    	return 0;
    }
    
    
  • 相关阅读:
    【EF Code First】CodeFirst初始配置
    【HTML5】炫丽的时钟效果Canvas绘图与动画基础练习
    C# MongoDB--时区问题(差了8小时)
    【HTML5】Canvas绘制基础
    判断数组与对象的方法
    javascript中的this
    实现动画效果
    js-改变this的指向
    js预编译
    js对象枚举
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8320821.html
Copyright © 2011-2022 走看看