博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ZOJ 3494
阅读量:5360 次
发布时间:2019-06-15

本文共 2519 字,大约阅读时间需要 8 分钟。

超级神奇有趣题。

AC自动机+数位DP。其实,数位DP在处理含有某些数字时特别不好处理,应该把它倒转为求不含有。这道题把数位DP+AC自动机结合起来,实在是很巧妙,把数字变为串来处理,强大!

要使用AC自动机来处理数位DP,首先就是要确定哪些状态由当前状态开始是不可以到达的,有哪些是可以到达的。这是显而易见的,因为既然是数位DP,必定涉及到数字的问题,每改变一个数字就会到达自动机上的一个状态,确定哪些状态可达或不可达是很有必要的。这就要求要构建trie图了。

其次就是DFS了,在进行DFS深搜前,要确定当前状态变更一个数字后的状态是否可达,再进行转移。

在这题,要处理前导0的问题,因为0000(十进制)里,其实只代表一个0,但可能会出现禁止状态(如二进制连续五个0违法,但四个0不违法)。

1 #include 
2 #include
3 #include
4 #include
5 #define LL long long 6 using namespace std; 7 const LL MOD=1000000009; 8 const int root=0; 9 int trie[2010][2],tot,bit[210]; 10 int next[2010][10],fail[2010]; 11 bool tag[2010]; 12 char str[210]; 13 LL dp[210][2010]; 14 int que[2010],head,tail; 15 16 void clr(int now){ 17 trie[now][0]=trie[now][1]=-1; 18 } 19 20 void insert(){ 21 int p=root,i=0,len=strlen(str); 22 while(i++
=len-i;i--){ 77 tmp=str[i]; 78 str[i]=str[len-i]; 79 str[len-i]=tmp; 80 } 81 } 82 83 int cal_next(int p,int j){ 84 if(tag[p]) return -1; 85 for(int k=3;k>=0;k--){ 86 p=trie[p][(j>>k)&1]; 87 if(tag[p]) return -1; 88 } 89 return p; 90 } 91 92 void Calculation(){ 93 for(int i=0;i<=tot;i++){ 94 for(int j=0;j<=9;j++){ 95 next[i][j]=cal_next(i,j); 96 } 97 } 98 } 99 100 LL dfs(int len,int j,bool limit,bool z){101 if(len==-1) return 1LL;102 if(!limit&&dp[len][j]!=-1) return dp[len][j];103 int up=limit?bit[len]:9;104 LL ans=0;105 if(z&&len>0){106 ans+=dfs(len-1,j,limit&&up==0,true);107 }108 else{109 if(next[j][0]!=-1&&!tag[next[j][0]])110 ans+=dfs(len-1,next[j][0],limit&&up==0,false);111 }112 for(int i=1;i<=up;i++){113 if(next[j][i]!=-1&&!tag[next[j][i]]){114 ans+=dfs(len-1,next[j][i],limit&&i==up,false);115 }116 }117 ans%=MOD;118 if(!limit) dp[len][j]=ans;119 return ans;120 }121 122 LL slove(){123 int len=strlen(str);124 len--;125 for(int i=len;i>=0;i--)126 bit[i]=str[i]-'0';127 return dfs(len,0,true,true);128 }129 130 int main(){131 int T,n,len;132 scanf("%d",&T);133 while(T--){134 memset(tag,false,sizeof(tag));135 memset(dp,-1,sizeof(dp));136 memset(fail,-1,sizeof(fail));137 scanf("%d",&n);138 tot=0;139 clr(root);140 for(int i=0;i
View Code

 

转载于:https://www.cnblogs.com/jie-dcai/p/4338329.html

你可能感兴趣的文章
Ctrl+Alt+Down/Up 按键冲突
查看>>
python序列化和json
查看>>
mongodb
查看>>
网格与无网格
查看>>
2018年3月份
查看>>
SSH-struts2的异常处理
查看>>
《30天自制操作系统》学习笔记--第14天
查看>>
LGPL协议的理解
查看>>
1、Python基础
查看>>
Unity The Tag Attribute Matching Rule
查看>>
试着理解下kvm
查看>>
WebService学习总结(二)--使用JDK开发WebService
查看>>
Tizen参考手机RD-210和RD-PQ
查看>>
竞价广告系统-位置拍卖理论
查看>>
策略模式 C#
查看>>
[模板]树状数组
查看>>
[HDU 6447][2018CCPC网络选拔赛 1010][YJJ's Salesman][离散化+线段树+DP]
查看>>
设计模式学习的好方法
查看>>
感谢Leslie Ma
查看>>
几种排序方法
查看>>