zoukankan      html  css  js  c++  java
  • LuoguP2657 [SCOI2009]windy数 【数位dp】By cellur925

    题目传送门

    题目大意:在A和B之间,包括A和B,总共有多少个不含前导零且相邻两个数字之差至少为2的正整数?


    显然是数位dp啦=w=。

    显然与上一位有关,我们$dfs$的时候就要记录$pre$。因为这是有前导零,所以我们需要分类讨论。

    当$ling==1&&i==0$,当前位还是前导零,那么我们之前放什么即可。为了放什么即可,我们开始可以设成-2.这样与谁的绝对值都会大于等于2了。(脆角!)

    否则的话按部就班放当前位就行了。

    Code

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 
     5 using namespace std;
     6 typedef long long ll;
     7 
     8 int len;
     9 int border[20];
    10 ll dp[20][13];
    11 ll a,b,ans1,ans2;
    12 
    13 ll dfs(int pos,int pre,int ling,int limit)
    14 {
    15     if(pos<1) return 1;
    16     if(!limit&&dp[pos][pre]!=-1&&!ling) return dp[pos][pre];
    17     ll tmp=0;
    18     ll lim=limit ? border[pos] : 9 ;
    19     for(int i=0;i<=lim;i++)
    20     {
    21         if(abs(i-pre)<2) continue;
    22         if(i==0&&ling) tmp+=dfs(pos-1,-2,1,(limit&&i==lim));
    23         else tmp+=dfs(pos-1,i,0,(limit&&i==lim));
    24     }
    25     if(!limit&&!ling) dp[pos][pre]=tmp;
    26     return tmp;
    27 }
    28 
    29 int main()
    30 {
    31     scanf("%lld%lld",&a,&b);
    32     a--;
    33     memset(dp,-1,sizeof(dp));
    34     while(a)
    35     {
    36         border[++len]=a%10;
    37         a/=10;
    38     }
    39     ans1=dfs(len,-2,1,1);
    40     len=0;
    41     memset(dp,-1,sizeof(dp));
    42     while(b)
    43     {
    44         border[++len]=b%10;
    45         b/=10;
    46     }
    47     ans2=dfs(len,-2,1,1);
    48     printf("%lld
    ",ans2-ans1);
    49     return 0;
    50 }
    View Code
  • 相关阅读:
    shell脚本之for循环
    shell脚本小集锦
    Java构建指定大小文件
    IntelliJ+Maven+Spring+Tomcat项目搭建(MAC)
    Git下基本命令操作
    Mac下IntelliJ的Git、GitHub配置及使用
    Git下的.DS_Store文件
    Mac下GitHub以及GitHub Desktop使用实战
    idea快捷键
    汉字获取首字符
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9788142.html
Copyright © 2011-2022 走看看