转载请注明原文地址http://www.cnblogs.com/LadyLex/p/8490222.html

之前学数位dp的时候底子没打扎实

虚的要死

这次正好有时间……刷了刷之前没做的题目

感觉自己脑洞不太够……比较经典的题或者见过的类似模型就能自己推出来,但是没有见过的模型就虚的要死(比如二进制数位DP)

感谢WQ的帮助,让我对数位DP的理解逐渐加深

那么我们总结一下这次做的题目……

bzoj4521

  记忆化搜索即可,水爆

  1. #include <cstring>
  2. #include <cstdio>
  3. using namespace std;
  4. #define RG register
  5. #define LL long long
  6. int bin[],cnt;
  7. LL poww[],f[][][][][][];
  8. inline int min(int a,int b){return a<b?a:b;}
  9. inline int max(int a,int b){return a>b?a:b;}
  10. inline LL dfs(int st,int pre,int comb,int maxcomb,bool have8,bool have4,bool limit)
  11. {
  12. if(st==)return maxcomb==;
  13. if(!limit&&f[st][pre][comb][maxcomb][have8][have4]!=-)
  14. return f[st][pre][comb][maxcomb][have8][have4];
  15. LL ret=;
  16. RG int i,tmp,lim=(limit)?bin[st]:;
  17. for(i=;i<lim;++i)
  18. {
  19. tmp=min((pre==i)?comb+:,);
  20. if(i==)
  21. {
  22. if(!have8)ret+=dfs(st-,i,tmp,max(tmp,maxcomb),,,);
  23. }
  24. else if(i==)
  25. {
  26. if(!have4)ret+=dfs(st-,i,tmp,max(tmp,maxcomb),,,);
  27. }
  28. else ret+=dfs(st-,i,tmp,max(tmp,maxcomb),have8,have4,);
  29. }
  30. if(limit)
  31. {
  32. tmp=min((pre==i)?comb+:,);
  33. if(i==)
  34. {
  35. if(!have8)ret+=dfs(st-,i,tmp,max(tmp,maxcomb),,,);
  36. }
  37. else if(i==)
  38. {
  39. if(!have4)ret+=dfs(st-,i,tmp,max(tmp,maxcomb),,,);
  40. }
  41. else ret+=dfs(st-,i,tmp,max(tmp,maxcomb),have8,have4,);
  42. }
  43. if(!limit)f[st][pre][comb][maxcomb][have8][have4]=ret;
  44. return ret;
  45. }
  46. inline LL calc(LL len)
  47. {
  48. LL ret=;cnt=;
  49. while(len)bin[++cnt]=len%,len/=;
  50. for(RG int i=;i<bin[];++i)ret+=dfs(,i,,,i==,i==,);
  51. return ret+dfs(,bin[],,,bin[]==,bin[]==,);
  52. }
  53. int main()
  54. {
  55. LL l,r,ans;RG int i;
  56. for(poww[]=i=;i<=;++i)poww[i]=poww[i-]*;
  57. scanf("%lld%lld",&l,&r);
  58. memset(f,-,sizeof(f)),ans=calc(r);
  59. if(l>1e10)ans-=calc(l-);
  60. printf("%lld\n",ans);
  61. }

BZOJ4521

bzoj4029

  假装他是数位dp的小模拟

  1. #include <cstdio>
  2. #include <cstring>
  3. using namespace std;
  4. #define RG register
  5. #define LL long long
  6. int br[],bl[],lr,ll,_10[];
  7. int main()
  8. {
  9. RG int pos,i,j,l,r,tmp,t,ans;
  10. scanf("%d",&t);
  11. for(_10[]=,i=;i<=;++i)_10[i]=_10[i-]*;
  12. while(t--)
  13. {
  14. scanf("%d%d",&l,&r),--l;
  15. ll=lr=;
  16. tmp=r;while(tmp)br[++lr]=tmp%,tmp/=;
  17. tmp=l;while(tmp)bl[++ll]=tmp%,tmp/=;
  18. if(lr!=ll)
  19. {
  20. if(l<*_10[ll])ans=*_10[ll];
  21. else if(*_10[ll+]<=r)ans=*_10[ll+];
  22. else if(bl[ll]==)ans=_10[ll+];
  23. else ans=_10[ll]*(bl[ll]+);
  24. }
  25. else
  26. {
  27. pos=ll;ans=;
  28. while(bl[pos]==br[pos]&&pos)ans=ans*+bl[pos],--pos;
  29. if(pos)
  30. {
  31. if(bl[pos]<&&<=br[pos])ans=(ans*+)* _10[pos];
  32. else ans=(ans*+bl[pos]+)* _10[pos];
  33. }
  34. }
  35. printf("%d\n",ans);
  36. }
  37. }

BZOJ4029

bzoj3209

  从低位往高位DP,带个组合数乱搞,比较水,没有打

bzoj3329

  两边同时异或一下x,然后由于异或是不进位的加法,所以发现性质是没有相邻的1,dp即可

  1. #include <cstring>
  2. #include <cstdio>
  3. using namespace std;
  4. #define mod 1000000007
  5. #define RG register
  6. #define LL long long
  7. namespace work1
  8. {
  9. LL f[][];int bin[],len;
  10. inline void init()
  11. {
  12. f[][]=,f[][]=;
  13. for(RG int i=;i<=;++i)
  14. f[i][]=f[i-][]+f[i-][],f[i][]=f[i-][];
  15. }
  16. inline LL dfs(int st,int pre,bool lim)
  17. {
  18. if(st==)return ;
  19. if(!lim)return pre?f[st][]:f[st][]+f[st][];
  20. if(bin[st])
  21. return pre?dfs(st-,,):(dfs(st-,,)+dfs(st-,,));
  22. return dfs(st-,,);
  23. }
  24. inline LL work(LL n)
  25. {
  26. if(!n)return ;
  27. len=;while(n)bin[++len]=n&,n>>=;
  28. return dfs(len-,,)+dfs(len-,,)-;
  29. }
  30. }
  31. namespace work2
  32. {
  33. struct matrix
  34. {
  35. int a[][];
  36. inline void clear(){memset(a,,sizeof(a));}
  37. inline void init(){memset(a,,sizeof(a));for(RG int i=;i<;++i)a[i][i]=;}
  38. inline matrix operator * (const matrix &b)const
  39. {
  40. RG int i,j,k;
  41. matrix c;c.clear();
  42. for(i=;i<;++i)
  43. for(k=;k<;++k)if(a[i][k])
  44. for(j=;j<;++j)if(b.a[k][j])
  45. c.a[i][j]=(c.a[i][j]+(LL)a[i][k]*b.a[k][j])%mod;
  46. return c;
  47. }
  48. inline void print()
  49. {
  50. for(RG int i=;i<;++i,printf("\n"))
  51. for(RG int j=;j<;++j)
  52. printf("%d ",a[i][j]);
  53. }
  54. }d,t;
  55. inline void init()
  56. {
  57. d.clear(),d.a[][]=d.a[][]=d.a[][]=d.a[][]=d.a[][]=;
  58. }
  59. inline matrix quick_mod(matrix di,LL mi)
  60. {
  61. matrix ret;ret.init();
  62. for(;mi;mi>>=,di=di*di)if(mi&)ret=ret*di;
  63. return ret;
  64. }
  65. inline int work(LL n)
  66. {
  67. t.clear(),t.a[][]=t.a[][]=,t=t*quick_mod(d,n);
  68. return t.a[][];
  69. }
  70. }
  71. int main()
  72. {
  73. RG int i,j,t;LL n;
  74. scanf("%d",&t);
  75. work1::init(),work2::init();
  76. while(t--)
  77. scanf("%lld",&n),printf("%lld\n%d\n",work1::work(n),work2::work(n));
  78. }

BZOJ3329

bzoj1799

  打表发现数位之和很少,枚举数位之和,但是我没想到dp的定义……

  然后看了一下题解的数组定义,难度适中吧……没有那么难,但是自己还是没想出来

  那个维护当前值然后每次cur=cur×10+i的很巧妙,没想出来……

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. #define RG register
  6. #define LL long long
  7. int bin[];
  8. inline int min(int a,int b){return a<b?a:b;}
  9. inline int max(int a,int b){return a>b?a:b;}
  10. int mod,mark[][][][];
  11. LL f[][][][];
  12. inline LL dfs(int st,int sum,int cur,bool lim)
  13. {
  14. if(st==)return cur==&&sum==;
  15. if(mark[st][sum][cur][lim]==mod)return f[st][sum][cur][lim];
  16. mark[st][sum][cur][lim]=mod;LL ret=;
  17. RG int i,l=max(,sum-(st-)* ),r=min( sum+,(lim?bin[st]:) );
  18. for(i=l;i<r;++i)ret+=dfs(st-,sum-i,(cur*+i)%mod,);
  19. if(lim && sum>=bin[st] )
  20. ret+=dfs(st-,sum-bin[st],(cur*+bin[st])%mod,);
  21. return f[st][sum][cur][lim]=ret;
  22. }
  23. inline LL calc(LL n)
  24. {
  25. RG int cnt=;LL ret=;
  26. while(n)bin[++cnt]=n%,n/=;
  27. memset(mark,,sizeof(mark));
  28. for(mod=;mod<=;++mod)ret+=dfs(cnt,mod,,);
  29. return ret;
  30. }
  31. int main()
  32. {
  33. RG int i,j;LL l,r;
  34. scanf("%lld%lld",&l,&r);
  35. printf("%lld\n",calc(r)-calc(l-));
  36. }

BZOJ1799

bzoj1183+bzoj2713

  这个和之前那个淘金很像……先预处理乘积,后面那个我一开始一直在想像上面1799的搞法带着乘积走

  然后发现不行,最后得到了提示,对于每一个乘积x,我去查询l/x,r/x区间内乘积为x的数就行了

  这个转化和之前数学上那个gcd很像:d|ij <==> d/gcd(i,d) | j

  啊我好蠢啊

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <cstdlib>
  5. using namespace std;
  6. #define RG register
  7. #define LL long long
  8. #define L 440000
  9. #define UL 44000
  10. int bin[],len,cnt;
  11. LL _9[],mul[L],f[][UL],l,r;
  12. inline void dfs1(int st,int pre,LL multi)
  13. {
  14. mul[++cnt]=multi;
  15. if(st==)return;
  16. for(RG int i=pre;i<;++i)
  17. if(multi*i<=r)dfs1(st+,i,multi*i);
  18. }
  19. inline int id(LL val){return lower_bound(mul+,mul+cnt+,val)-mul;}
  20. inline LL dfs(int st,int mul_id,bool limit)
  21. {
  22. if(mul[mul_id]>_9[st])return ;
  23. if(st==)return ;
  24. RG int i,lim=(limit?bin[st]:);
  25. LL ret=;
  26. for(i=;i<lim;++i)
  27. if(mul[mul_id]%i==)
  28. ret+=f[st-][id(mul[mul_id]/i)];
  29. if(lim&&bin[st])
  30. if(mul[mul_id]%bin[st]==)
  31. ret+=dfs(st-,id(mul[mul_id]/bin[st]),);
  32. return ret;
  33. }
  34. inline LL query(int id,LL n)
  35. {
  36. LL ret=;len=;
  37. while(n)bin[++len]=n%,n/=;
  38. for(RG int i=;i<len;++i)ret+=f[i][id];
  39. return ret+dfs(len,id,);
  40. }
  41. inline LL calc(LL n)
  42. {
  43. if(!n)return ;LL ret=;
  44. for(RG int i=;mul[i]<=n&&i<=cnt;++i)
  45. ret+=query(i,n/mul[i]);
  46. return ret;
  47. }
  48. int main()
  49. {
  50. RG int i,j,k;
  51. scanf("%lld%lld",&l,&r);
  52. mul[++cnt]=;
  53. dfs1(,,),sort(mul+,mul+cnt+),
  54. cnt=unique(mul+,mul+cnt+)-mul-;
  55. for(_9[]=i=;i<=;++i)_9[i]=_9[i-]*;
  56. for(f[][]=,i=;i<=;++i)f[][i]=;
  57. for(i=;i<=;++i)
  58. for(j=;j<=cnt;++j)if(f[i-][j])
  59. for(k=;k<=;++k)f[i][id(mul[j]*k)]+=f[i-][j];
  60. printf("%lld\n", calc(r) - calc(l-) );
  61. }

BZOJ1183+BZOJ2713

bzoj3530

  不知道怎么混进来的AC自动机题目

  前导0的处理需要注意,一开始没有想好

  1. #include <cstdio>
  2. #include <cstring>
  3. using namespace std;
  4. #define L 1510
  5. #define RG register
  6. #define mod 1000000007
  7. char s[L],str[L];
  8. bool ban[L];
  9. int n,cnt,ch[L][],fail[L],q[L],hd,tl,plan[L][L];
  10. inline int dfs(int rt,int left)
  11. {
  12. if(ban[rt])return plan[rt][left]=;
  13. if(plan[rt][left])return plan[rt][left];
  14. int ret=;
  15. for(RG int i=;i<;++i)
  16. if(!ban[ch[rt][i]])
  17. ret=(ret+dfs(ch[rt][i],left-))%mod;
  18. return plan[rt][left]=ret;
  19. }
  20. #define id(c) ((c)-'0')
  21. signed main()
  22. {
  23. RG int i,j,m,rt,l,d,ans=,good=;
  24. scanf("%s",s+),n=strlen(s+);
  25. scanf("%d",&m);
  26. cnt=;
  27. for(i=;i<=m;++i)
  28. {
  29. scanf("%s",str+),l=strlen(str+);
  30. for(rt=,j=;j<=l;++j)
  31. {
  32. d=str[j]-'';
  33. if(!ch[rt][d])ch[rt][d]=++cnt;
  34. rt=ch[rt][d];
  35. if(ban[rt])break;
  36. }
  37. ban[rt]=;
  38. }
  39. for(hd=,tl=,i=;i<;++i)
  40. if(ch[][i])q[++tl]=ch[][i],fail[ch[][i]]=;
  41. else ch[][i]=;
  42. while(hd<=tl)
  43. for(rt=q[hd++],i=;i<;++i)
  44. if(ch[rt][i])d=ch[rt][i],fail[d]=ch[fail[rt]][i],ban[d]|=ban[fail[d]],q[++tl]=d;
  45. else ch[rt][i]=ch[fail[rt]][i];
  46. for(i=;i<=cnt;++i)if(!ban[i])plan[i][]=;
  47. for(i=;i<=cnt;++i)if(!ban[i])
  48. for(j=;j<n;++j)if(!plan[i][j])dfs(i,j);
  49. for(i=;i<n;++i)for(j=;j<;++j)
  50. ans=(ans+plan[ch[][j]][i-])%mod;
  51. for(rt=,i=;i<=n;++i)
  52. {
  53. for(d=s[i]-'',j=(i==?:);j<d;++j)
  54. if(!ban[ch[rt][j]])ans=(ans+plan[ch[rt][j]][n-i])%mod;
  55. rt=ch[rt][d];
  56. if(ban[rt]){good=;break;}
  57. }
  58. printf("%d\n",ans+good);
  59. }

BZOJ3530

uoj86

题解在这里面,综合感不错的题目……

bzoj3652

相当于两部分分开求和再除总数然后加权

第二部分求异或和很好想,统计每位0/1个数然后搞就行

关于第一部分………在%wq的思路之后打过去了

第一部分相当于对于每一个数选一个数和它异或和最大

由于选的那个数也要在n的范围内,所以我们不太好搞

这样,我们正难则反,先认为每个数的每一位都能贡献上,再减去多余的贡献

由于n的二进制第一位一定是1,所以在2^(len-1)到n-1这些数一定每一位都能贡献上

那么我们一开始就拿着0~2^(len-1)-1这些数(len代表n的二进制长度),维护剩下多少数

从n的高位往低位考虑,如果n的某一位是1,那么这一位如果填0的话,

现在这一位为1的数(正好占一半)就一定能贡献后面所有位的值(即他们一定不会超限,所以后面可以随意填)

那么我们把它们扔掉,即更改剩下数的多少

这个和一开始分析的最高位的情况类似

反之,如果为0,那么这一位为0的所有数(也是占一半)由于不能填1而无法贡献这一位的异或值

那么我们在答案中减去对应的值

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. using namespace std;
  5. #define RG register
  6. #define LL long long
  7. #define db double
  8. LL bin[];
  9. int bit[],len;
  10. int main()
  11. {
  12. RG int i;LL n,m,tmp,cnt0,cnt1;
  13. db val1=,val2=,p,q;
  14. for(bin[]=i=;i<=;++i)bin[i]=bin[i-]<<;
  15. scanf("%lld%lf",&n,&p),m=n-;
  16. tmp=m;while(tmp)bit[++len]=tmp&,tmp>>=;
  17. for(i=len;~i;--i)
  18. {
  19. tmp=n>>(i+),cnt0=cnt1=tmp*bin[i];
  20. if(n&bin[i])cnt0+=bin[i],cnt1+=(bin[i]-)&n;
  21. else cnt0+=(bin[i]-)&n;
  22. val2+=2.0*cnt0*cnt1*bin[i];
  23. }
  24. val2/=n*1.0*n;
  25. val1=n*1.0*(bin[len]-);tmp=bin[len];
  26. for(i=len;i;--i)
  27. if(bit[i])tmp>>=;
  28. else val1-=(tmp>>)*1.0*bin[i-];
  29. printf("%.10lf\n",p*val1/n+(-p)*val2 );
  30. }

BZOJ3652

bzoj4513

感觉是上面一题的加强版

自己想的是dfs打法,但是由于情况太多无法手动分类讨论,打不出来

数组定义定义f[i][2][2][2],后面三个0/1分别代表是否满足i<=n,j<=m,i^j>=k

现在我发现的AC写法(茴香豆的茴有四种写法你知道嘛)

1.(大部分网上题解使用的)4维数组dp

发现网上大部分人是用的迭代dp的打法

和我定义是一样的,可是……

代码实现出人意料的简洁

dp写法和dfs写法的确是各有所长

dp适合用很多for循环和边界特判无脑处理掉大量的分类讨论

而dfs适合无法很好用for循环枚举的东西

Ps:dp写法有一个地方不是太懂,就是为什么最后要把数组的每个元素都计算一遍

我们需要的答案难道不就是ans[1][1][1]吗

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <cstring>
  4. using namespace std;
  5. #define RG register
  6. #define LL long long
  7. LL n,m,k,bin[],f_ge[][][][],f_sum[][][][];
  8. int main()
  9. {
  10. RG int mod,i,ta,tb,tc,a,b,c,x,y,z,t,len,lena,lenb,lenc,bita,bitb,bitc;
  11. LL ans,tmp;scanf("%d",&t);
  12. while(t--)
  13. {
  14. scanf("%lld%lld%lld%d",&n,&m,&k,&mod),--n,--m;
  15. lena=lenb=lenc=;
  16. tmp=n;while(tmp)++lena,tmp>>=;
  17. tmp=m;while(tmp)++lenb,tmp>>=;
  18. tmp=k;while(tmp)++lenc,tmp>>=;
  19. len=max(lena,max(lenb,lenc));
  20. for(bin[]=i=;i<=len;++i)bin[i]=(bin[i-]<<)%mod;
  21. memset(f_ge,,sizeof(f_ge)),memset(f_sum,,sizeof(f_sum));
  22. f_ge[len+][][][]=;ans=;
  23. for(i=len;~i;--i)
  24. {
  25. bita=(n>>i)&,bitb=(m>>i)&,bitc=(k>>i)&;
  26. for(a=;a<;++a)for(b=;b<;++b)for(c=;c<;++c)
  27. if(f_ge[i+][a][b][c])
  28. for(x=;x<;++x)
  29. {
  30. if(a && x>bita)break;
  31. for(y=;y<;++y)
  32. {
  33. if(b && y>bitb)break;
  34. z=x^y;
  35. if(c && z<bitc)continue;
  36. ta=(a && bita==x)?:,tb=(b && bitb==y)?:,tc=(c && bitc==z)?:;
  37. f_ge[i][ta][tb][tc]=(f_ge[i][ta][tb][tc]+f_ge[i+][a][b][c])%mod;
  38. f_sum[i][ta][tb][tc]=( f_sum[i][ta][tb][tc]+f_sum[i+][a][b][c])%mod;
  39. if(z)f_sum[i][ta][tb][tc]=( f_sum[i][ta][tb][tc]+ bin[i]*f_ge[i+][a][b][c]%mod )%mod;
  40. }
  41. }
  42. }
  43. k%=mod;
  44. for(a=;a<;++a)for(b=;b<;++b)for(c=;c<;++c)
  45. ans=(ans+f_sum[][a][b][c]-k*f_ge[][a][b][c]%mod+mod)%mod;
  46. printf("%lld\n",ans);
  47. }
  48. }

BZOJ4513

啊……我要再研究一下dfs写法,看看能不能打出来

upd:我完蛋了,我打不出来2333

2.wq式dp打法,强大又快速,wq Orzzzzzzzzzzzzzzzzzzzzzzzz

很巧妙,刷新了我对数位Dp的认识,让我理解更加深入了

让wq讲了一个多小时,感觉自己智商掉没了2333

但是还是不太懂,无法用语言描述……

等我更强了再来补这个做法……

bzoj3326

思路大概是很清真的,总的来说就是预处理前i位数的子串和,以及前缀子串之和,然后按照数位DP那样限制转移

但是……那个转移的式子……

啊真是让人痛苦,那个式子我总共大改了5遍才打过,并且有很多一开始没有注意到的细节

以后做题必须要先想好式子

每一项是什么为什么都要想清楚

要不特别耽误时间……有的时候船到桥头……就翻船了……

感觉思维严谨性得到了提高2333

  1. #include <cstdio>
  2. #include <cstring>
  3. using namespace std;
  4. #define RG register
  5. #define mod 20130427
  6. #define N 100010
  7. #define LL long long
  8. char cB[<<],*S=cB,*T=cB;
  9. #define getc (S==T&&(T=(S=cB)+fread(cB,1,1<<15,stdin),S==T)?0:*S++)
  10. inline int read()
  11. {
  12. RG int x=;RG char c=getc;
  13. while(c<''|c>'')c=getc;
  14. while(c>=''&c<='')x=*x+(c^),c=getc;
  15. return x;
  16. }
  17. inline int Sum(int a){return ((LL)a*(a+1ll)/)%mod;}
  18. inline int max(int a,int b){return a>b?a:b;}
  19. inline int min(int a,int b){return a<b?a:b;}
  20. int ge2[N],sum2[N],ge3[N],sum3[N],no_zero_sum3[N],B,lena,bit[N],lenb,bin[N];
  21. inline int calc(bool start,int left,int lim,int cnt,int sum,int sum_of_substring )
  22. {
  23. if(lim==)return ;
  24. if(start)
  25. return
  26. (
  27. (LL) Sum(lim-) * ge2[left] %mod * bin[left] %mod + //前与后连接之后前面的贡献
  28. (LL) ( lim - ) %mod * sum3[left] %mod + no_zero_sum3[left] %mod +//后面的子串
  29. (LL) ( lim - ) %mod * sum2[left] %mod//前与后连接之后后面的贡献
  30. )%mod;
  31. int new_sum=( (LL) sum * B %mod * lim %mod + (LL) Sum(lim-) * cnt %mod ) %mod;
  32. return
  33. (
  34. (LL) sum_of_substring * lim %mod * bin[left] %mod + //之前的子串
  35. (LL) new_sum * ge2[left] %mod * bin[left] %mod + //前与后连接之后前面的贡献
  36. (LL) lim %mod * sum3[left] %mod +//后面的子串 不乘cnt
  37. (LL) cnt * lim %mod * sum2[left] %mod//前与后连接之后后面的贡献 ,要乘cnt 因为再前面不同
  38. )%mod;
  39. }
  40. inline int dfs(bool start,int st,int cnt,int sum,int sum_of_substring)
  41. {
  42. if(st==)return ;
  43. int new_sum=( (LL) sum * B %mod + (LL) ( cnt + ) * bit[st] %mod )%mod;
  44. return
  45. ( new_sum + calc(start, st- , bit[st] , cnt + , sum , sum_of_substring ) +
  46. dfs(, st - , cnt + , new_sum , (sum_of_substring + new_sum)%mod ) )%mod;
  47. }
  48. signed main()
  49. {
  50. RG int i,j,len,ans;
  51. B=read(),lena=read();
  52. for(i=lena;i;--i)bit[i]=read();
  53. lenb=read();len=max(lena,lenb);
  54. if(lena>||bit[]>)
  55. {
  56. --bit[],j=;
  57. while(bit[j]<)bit[j]+=B,--bit[j+],++j;
  58. while(lena>&&!bit[lena])--lena;
  59. }
  60. for(bin[]=ge2[]=i=;i<=len;++i)
  61. {
  62. bin[i]=(LL)bin[i-]*B%mod;
  63. ge2[i]=( ge2[i-] + bin[i] )%mod;
  64. ge3[i]=(LL) Sum(i) * bin[i] %mod;
  65. sum2[i]=( (LL) sum2[i-] * B %mod + Sum ( bin[i] - ) )%mod;
  66. sum3[i]=( (LL) Sum(B-) * bin[i-] %mod * ge2[i-] %mod + (LL)B * sum2[i-] %mod + (LL) B * sum3[i-] %mod )%mod;
  67. no_zero_sum3[i]=( (LL) Sum(B-) * bin[i-] %mod * ge2[i-] %mod +
  68. (LL) (B - ) * sum2[i-] %mod + (LL) (B - ) * sum3[i-] %mod + no_zero_sum3[i-] )%mod;
  69. }
  70. ans=mod-dfs(,lena,,,);
  71. for(i=lenb;i;--i)bit[i]=read();
  72. printf("%d\n",(ans+dfs(,lenb,,,))%mod);
  73. }

bzoj3326

其实还有另外一种思路,那就是反过来从前往后走,并且用矩阵乘优化

这个是wq的原创思路……

bzoj3598

  没做呢,听说挺简单,但是我没想出来

  这次时间不够了……不想怂题解

  有时间再做……

这次做的题就是这么多……接下来要去找“有思维难度的DP题”了……加油咯……

数位DP复习小结的更多相关文章

  1. 数位DP复习笔记

    前言 复习笔记第五篇.(由于某些原因(见下),放到了第六篇后面更新)CSP-S RP++. luogu 的难度评级完全不对,所以换了顺序,换了别的题目.有点乱,见谅.要骂就骂洛谷吧,原因在T2处 由于 ...

  2. 数位DP之小小结

    资料链接:http://wenku.baidu.com/view/9de41d51168884868662d623.html http://wenku.baidu.com/view/d2414ffe0 ...

  3. 数位dp小结

    数位dp其实就是一种用来求区间[l, r]满足条件的数的个数.数位是指:个十百千万,而在这里的dp其实相当于暴力枚举每一位数. 我们通过把l, r的每位数分解出来,然后分别求r里满足条件的数有多少,l ...

  4. 数位dp小结以及模板

    这里是网址 别人的高一啊QAQ.... 嗯一般记忆化搜索是比递推好写的所以我写的都是dfs嗯......(因为我找不到规律啊摔,还是太菜.....) 显然这个东西的条件是非常的有套路..但是不管怎么样 ...

  5. 算法复习——数位dp

    开头由于不知道讲啥依然搬讲义 对于引入的这个问题,讲义里已经很清楚了,我更喜欢用那个建树的理解···· 相当于先预处理f,然后从起点开始在树上走··记录目前已经找到了多少个满足题意的数k,如果枚举到第 ...

  6. 算法复习——数位dp(不要62HUD2089)

    题目 题目描述 杭州人称那些傻乎乎粘嗒嗒的人为 62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司 ...

  7. 数位DP入门:(bzoj1833+3209)

    //我是来看文章创建时间的= = 膜拜了一下蔡大神.... 人生第一道自己写的数位DP...好吧以前是看题解然后也不知道为什么就过了的>_< 虽然说现在还是只会裸题= = 数位DP介绍: ...

  8. [poj3252]Round Numbers_数位dp

    Round Numbers poj3252 题目大意:求一段区间内Round Numbers的个数. 注释:如果一个数的二进制表示中0的个数不少于1的个数,我们就说这个数是Round Number.给 ...

  9. [bzoj1026][SCOI2009]windy数_数位dp

    windy数 bzoj-1026 题目大意:求一段区间中的windy数个数. 注释:如果一个数任意相邻两位的差的绝对值都不小于2,这个数就是windy数,没有前导0.$区间边界<=2\cdot ...

随机推荐

  1. Makefile 学习记录一

    2019年2月5日10:18:13  大年初一 整理 uboot-2018-11 源代码 根目录下的 Makefile . ifeq ("$(origin O)", "c ...

  2. 【LeetCode21】Merge Two Sorted Lists★

    1.题目描述: 2.解题思路: 本题是要合并两个已经有序的单链表,思路很简单,有两种方法:非递归和递归. 3.Java代码: (1)非递归: 为方便操作,定义一个辅助的头节点,然后比较原来两个链表的头 ...

  3. python基础1之python介绍、安装、变量和字符编码、数据类型、输入输出、数据运算、循环

    开启python之路 内容概要: 一.python介绍 二.安装 三.第一个python程序 四.变量和字符编码 五.用户输入 六.数据类型 七.一切皆对象 八.数据运算 九.if else 流程判断 ...

  4. WPF编程,通过【帧】动态更改控件属性的一种方法。

    原文:WPF编程,通过[帧]动态更改控件属性的一种方法. 版权声明:我不生产代码,我只是代码的搬运工. https://blog.csdn.net/qq_43307934/article/detail ...

  5. Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法

    #define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0) #define _IOR(type,nr,size)    _IOC(_IOC_RE ...

  6. 理解 NgModelController 中相关方法和属性

    1. 理解$formatters和$parsers方法 angular的双向绑定可以实现view和model中的值自动同步,但有时候我们不想让用户输入的(view值)和发送给后台的(model值)并不 ...

  7. 升级webpack2

    更新:webpack3已经出来了,官方说从2到升级到3不用改一行配置,98%的人没有错误. 项目中用的是webpack1.webpack2已经出来一段时间了.决定升级.其实改动不是很大.修改加测试共花 ...

  8. 利用privoxy劫持http网站数据,插入广告,获取用户名,密码

    看了几篇privoxy的文章,感觉讲的都不详细,在此整理一遍. 注:本文下面的内容仅讨论思路,作为技术交流之用,请勿用作非法途径. Privoxy是一款带过滤功能的代理服务器,针对HTTP.HTTPS ...

  9. JQuery快速入门-Ajax

    一.AJAX概述 概念:AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). 优点:通过在后台与服务器进行少量数据交换,AJAX ...

  10. WinForm 随手记

    从今天开始咱们正式进入WinForm开发模式 首先很官方的介绍下什么是winform:客户端应用程序:C/S 这就是winform 有什么特别特别重要的特点呢:可以操作用户电脑上的文件 举个简单的例子 ...