zoukankan      html  css  js  c++  java
  • Luogu-P2657 [SCOI2009]windy数

    题目

    题目链接

    测试得分:  100

    主要算法 :  数位DP

    题干:

       数位DP板子

    分析:  

    1.   预处理出f[i][j]长度为i且最高位为j的windy数个数

    void Init()
    {
        FORa(i,0,M) f[1][i]=1;
        FORa(i,2,N)
            FORa(j,0,M)
                FORa(k,0,M)        
                    if(abs(j-k)>=2) f[i][j]+=f[i-1][k];//预处理 
    }

      2.  数位DP转移

        int len=0,ans=0,y;
        while(n) s[++len]=n%10,n/=10;
        FORa(i,1,len-1)
            FORa(j,1,M)
                ans+=f[i][j];//位数小于n的位数的,全部累加起来
        FORa(i,1,s[len]-1) ans+=f[len][i];//位数一样但是小于最高位的累加 
        FORs(i,len-1,1)//i从最高位后开始枚举
        {
            FORa(j,0,s[i]-1)//j是i位上的数 
                if(abs(j-s[i+1])>=2)//判断和上一位(i+1)相差2以上)    
                    ans+=f[i][j]; //如果是 ans就累加 
            if(abs(s[i+1]-s[i])<2)       break;
        }

      代码

      

    #include<math.h>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define FORa(i,s,e) for(int i=s;i<=e;i++)
    #define FORs(i,s,e) for(int i=s;i>=e;i--)
    #define gc pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),stdin)?EOF:*pa++
    #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout);
    
    using namespace std;
    char buf[100000],*pa,*pb;
    inline int read();
    
    const int N=10,M=9;
    int f[N+1][M+1],fpow[N+1],s[N+1];
    int a,b;
    //f[i][j]代表的是一共有i位,最高位为j的windy数个数 
    void Init()
    {
        FORa(i,0,M) f[1][i]=1;
        FORa(i,2,N)
            FORa(j,0,M)
                FORa(k,0,M)        
                    if(abs(j-k)>=2) f[i][j]+=f[i-1][k];//预处理 
    }
    int Count(int n)
    {
        int len=0,ans=0,y;
        while(n) s[++len]=n%10,n/=10;
        FORa(i,1,len-1)
            FORa(j,1,M)
                ans+=f[i][j];//位数小于n的位数的,全部累加起来
        FORa(i,1,s[len]-1) ans+=f[len][i];//位数一样但是小于最高位的累加 
        FORs(i,len-1,1)//i从最高位后开始枚举
        {
            FORa(j,0,s[i]-1)//j是i位上的数 
                if(abs(j-s[i+1])>=2)//判断和上一位(i+1)相差2以上)    
                    ans+=f[i][j]; //如果是 ans就累加 
            if(abs(s[i+1]-s[i])<2)       break;
        }
        return ans;
    }
    int main()
    {
        Init();
        scanf("%d%d",&a,&b);
        printf("%d",Count(b+1)-Count(a));
        return 0;
    }
    inline int read()
    {
        register char c(gc);register int f(1),x(0);
        while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;
        while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;
        return x*f;
    }

    总结:

      1.确定每一个位的数的范围

      2.状态的确定性

  • 相关阅读:
    mongodb 逻辑操作符
    mongodb 操作符
    js 对象拷贝的三种方法,深拷贝函数。
    html语义化
    移动端meta
    onmouseOver、onmouseOut 和 onmouseEnter、onmouseLeave的区别
    javascript阻止事件冒泡和浏览器的默认行为
    js中return的用法
    Ubuntu联网设置
    视窗宽高offset、client、scroll
  • 原文地址:https://www.cnblogs.com/SeanOcean/p/11348744.html
Copyright © 2011-2022 走看看