传送门

md直接wa了78次,身败名裂

没学过数位DP硬搞了一道数位DP的模板题,感觉非常的愉(sha)悦(cha)。

二分转化枚举思想。首先DP预处理出来$f[i][j]$表示有$i$位且第$i$位为$j$的windy数有多少个,然后搞个$g[i]$表示$i$位上可以有多少个windy数。然后二分出来最大的小于$A$和$B$的windy数。相减就好了。

//BZOJ 1026
//by Cydiater
//2016.10.24
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <iomanip>
#include <bitset>
using namespace std;
#define ll long long
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define down(i,j,n)     for(int i=j;i>=n;i--)
const int oo=0x3f3f3f3f;
inline ll read(){
    char ch=getchar();ll x=0,f=1;
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll f[15][15],A,B,g[15],ten[15];
namespace solution{
    void init(){
        A=read();B=read();
        ll tmp=1;
        up(i,1,14){
            ten[i]=tmp;
            tmp*=10LL;
        }
    }
    ll col(ll pos,ll re,ll last){
        if(pos==0)return 0;
        if(last==-1){
			if(pos==1){
				if(re<=f[pos][0])return 0;
				re-=f[pos][0];
			}
            up(i,1,9){
                if(re<=f[pos][i])return  ten[pos]*i+col(pos-1,re,i);
                re-=f[pos][i];
            }
        }else{
			if(pos==1&&last-2>=0){
				if(re<=f[pos][0])return 0;
				re-=f[pos][0];
			}
            if(last-2>=0){
                ll sum=0;
                up(i,2,9)sum+=f[pos-1][i];
                if(re<=sum)      return col(pos-1,re,0);
                else            re-=sum;
            }
            up(i,1,9)if(abs(i-last)>=2){
                if(re<=f[pos][i])    return ten[pos]*i+col(pos-1,re,i);
                re-=f[pos][i];
            }
        }
    }
    ll check(ll id){
        ll last=-1,ans=0,high=0;
        down(i,11,1)if(g[i]<id){
            high=i;
            id-=g[i];
            break;
        }
        ans=col(high+1,id,-1);
        return ans;
    }
    ll get(ll num){
        ll leftt=0,rightt=10000000000LL,mid;
        while(leftt+1<rightt){
            mid=(leftt+rightt)>>1;
            if(check(mid)<=num)   leftt=mid;
            else                rightt=mid;
        }
        if(check(rightt)<=num)       return rightt;
        return leftt;
    }
    void slove(){
        memset(f,0,sizeof(f));
        up(i,0,9)f[1][i]=1;
        up(i,2,14)up(j,0,9){
            up(k,j+2,9)f[i][j]+=f[i-1][k];
            down(k,j-2,0)f[i][j]+=f[i-1][k];
        }
		if(A>B)swap(A,B);
        memset(g,0,sizeof(g));
        g[0]=1;
        up(i,1,14){
            g[i]+=g[i-1];
            up(j,1,9)g[i]+=f[i][j];
        }
        cout<<get(B)-get(A-1)<<endl;
    }
}
int main(){
	//freopen("input.in","r",stdin);
	//freopen("out1.out","w",stdout);
    using namespace solution;
    init();
    slove();
    return 0;
}

BZOJ1026: [SCOI2009]windy数的更多相关文章

  1. BZOJ1026 SCOI2009 windy数 【数位DP】

    BZOJ1026 SCOI2009 windy数 Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B ...

  2. BZOJ1026: [SCOI2009]windy数[数位DP]

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 6346  Solved: 2831[Submit][Sta ...

  3. 【数位DP】bzoj1026: [SCOI2009]windy数

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 4163  Solved: 1864[Submit][Sta ...

  4. bzoj1026: [SCOI2009]windy数(数位dp)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 8203  Solved: 3687[Submit][Sta ...

  5. 2018.06.30 BZOJ1026: [SCOI2009]windy数(数位dp)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec Memory Limit: 162 MB Description windy定义了一种windy数.不含前导零且相邻两 ...

  6. bzoj千题计划117:bzoj1026: [SCOI2009]windy数

    http://www.lydsy.com/JudgeOnline/problem.php?id=1026 数位DP 如果前一位填的是0, 0是前导0,下一位可以随便填 0不是前导0,下一位不能填1 为 ...

  7. bzoj1026: [SCOI2009]windy数(传说你是数位DP)

    1026: [SCOI2009]windy数 题目:传送门 题解: 其实之前年少无知的时候好像A过...表示当时并不知道什么数位DP 今天回来深造一发... 其实如果对这个算法稍有了解...看到这题的 ...

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

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

  9. [BZOJ1026][SCOI2009]windy数 解题报告|数位dp

    Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? 一直 ...

随机推荐

  1. 深入解析Windows操作系统笔记——CH3系统机制

    3.系统机制 微软提供了一些基本组件让内核模式的组件使用: 1.陷阱分发,包括终端,延迟的过程调用(DPC),异步过程调用(APC),异常分发以及系统服务分发 2.执行体对象管理器 3.同步,包括自旋 ...

  2. javascript - 享元模式

    享元模式笔记  运用共享技术有效的支持大量的细粒度对象,避免对象间拥有相同内容造成多余的开销  享元模式主要还是对其数据.方法共享分离,它将数据和方法分成内部数据.内部方法和外部数据.外部方法.  内 ...

  3. linux ssh和scp实例

    ssh 192.160.1.100 -p 40012 scp user 192.169.72.2:/ scp -i /id_rsa -P40027 root@221.212.235.17:/sdzw/ ...

  4. [Java入门笔记] 面向对象编程基础(三):成员变量和局部变量

    在类中,变量根据定义的位置不同,可以分为成员变量和局部变量.

  5. Forbidden You don't have permission to access / on this server PHP

    在新安装的谷歌游览器里,打不了PHP网站了,错误显示: Forbidden You don't have permission to access / on this server. 原因还是配置权限 ...

  6. memcache+magent的高可用

    memcache+magent的高可用 一.安装步骤: 1.编译安装libevent: wget http://monkey.org/~provos/libevent-1.4.9-stable.tar ...

  7. Java 6 JVM参数选项大全(中文版)

    原文来自: http://kenwublog.com/docs/java6-jvm-options-chinese-edition.htm 本文是基于最新的SUN官方文档Java SE 6 Hotsp ...

  8. 深入理解Java反射

    要想理解反射的原理,首先要了解什么是类型信息.Java让我们在运行时识别对象和类的信息,主要有2种方式:一种是传统的RTTI,它假定我们在编译时已经知道了所有的类型信息:另一种是反射机制,它允许我们在 ...

  9. 洛谷练习P2279 P1346

    题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状 ...

  10. 洛谷P1134 阶乘问题[数论]

    题目描述 也许你早就知道阶乘的含义,N阶乘是由1到N相乘而产生,如: 12! = 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x 10 x 11 x 12 = 479,001, ...