luogu2657bzoj1026 [SCOI2009]windy数 [动态规划 数位dp]

Posted lxyyyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu2657bzoj1026 [SCOI2009]windy数 [动态规划 数位dp]相关的知识,希望对你有一定的参考价值。

P2657 [SCOI2009]windy数

bzoj1026 

一本通说这是一道数位dp模板题 emmmmm 就是逐位确定

f[i][j]表示填了i位数其最高位数字为j 然后就去求可能方案数

分为

  • 不满足x的位数的严格小于x的全部情况
  • 和x的位数相同 但最高位小于x的最高为的全部方案数
  • 和x的位数相同 有一位比x的对应位数小的全部方案数 其余位数对应数字都相同(这是数位dp常用的一个性质:对于一个小于n的数 它从高位到低位一定会出现某一位上的数字小于n所对应这一位上的数字)

PS 因为x不一定为windy数 所以在第三种方案时 我们遇到不满足为windy数时退出

只是我还没搞懂为什么输出dp(b)-dp(a-1)会错一个点

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<stack>
 7 #include<algorithm>
 8 using namespace std;
 9 #define ll long long
10 #define rg register
11 const int N=2000000000+5,pw=11,inf=0x3f3f3f3f,P=19650827;
12 int a,b,f[pw+5][pw+5];
13 ll base[pw+5];
14 template <class t>void rd(t &x)
15 {
16     x=0;int w=0;char ch=0;
17     while(!isdigit(ch)) w|=ch==-,ch=getchar();
18     while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
19     x=w?-x:x;
20 }
21 
22 void prepare()
23 {
24     base[0]=1;
25     for(rg int i=1;i<=pw;++i) base[i]=base[i-1]*10;
26     for(rg int i=0;i<10;++i) f[1][i]=1;//
27     for(rg int i=2;i<=pw;++i)
28     for(rg int j=0;j<10;++j)
29     for(rg int k=0;k<10;++k)
30     if(abs(j-k)>=2) f[i][j]+=f[i-1][k]; 
31 }
32 
33 int dp(int x)
34 {
35     int p,ans=0;
36     for(p=0;p<=pw;++p) if(base[p]>x) break;
37     if(!p) return ans; 
38     for(rg int i=1;i<p;++i)
39     for(rg int j=1;j<10;++j)
40     ans+=f[i][j];//不满p位的
41     int pre=x/base[p-1];x%=base[p-1];
42     for(rg int i=1;i<pre;++i)
43     ans+=f[p][i];//满足p位 但第p位数字小于x的
44     for(rg int i=p-1;i>0;--i)
45     {
46         int cur=x/base[i-1];
47         for(rg int j=0;j<cur;++j)
48         if(abs(pre-j)>=2) ans+=f[i][j];
49         if(abs(pre-cur)<2) break; 
50         pre=cur,x%=base[i-1];
51      } 
52      return ans;
53 }
54 
55 int main()
56 {
57     //freopen("in.txt","r",stdin);
58     //freopen("nocows.out","w",stdout);
59     prepare();
60     rd(a),rd(b);
61     printf("%d",dp(b+1)-dp(a));
62     return 0;
63 }

 

以上是关于luogu2657bzoj1026 [SCOI2009]windy数 [动态规划 数位dp]的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1026 [SCOI2009]windy数

luogu P2657 [SCOI2009]windy数 数位dp 记忆化搜索

Luogu P2657 [SCOI2009]windy数

luogu P2657 [SCOI2009]windy数 数位dp入门题

BZOJ1026 [SCOI2009]windy数

BZOJ1026: [SCOI2009]windy数