• [BZOJ1026] [洛谷P2657] [SCOI2009]windy数 数位DP


    题目描述

    windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,

    在A和B之间,包括A和B,总共有多少个windy数?

    输入格式

    包含两个整数,A B。

    输出格式

    一个整数

    输入输出样例

    输入 #1

    1 10
    

    输出 #1

    9
    

    输入 #2

    25 50
    

    输出 #2

    20
    

    说明/提示

    100%的数据,满足 (1 <= A <= B <= 2000000000)


    题解

    数位DP

    (f[i][j])表示 (i) 位数,最高位为 (j)的符合条件的数的个数。

    则$ f[i][j]=sum_{|j−k|≤2}f[i−1][k] $。

    预处理(f)数组后进行数位DP。

    先填充位数不满的,再由高位向低位将此位不满的加入答案。

    且若当前位于上一位数产生冲突导致不会再有满足条件的数时,跳出循环。

    转换询问区间为([1, n))则更易简单处理。

    code

    #include <iostream>
    #include <cstdio>
    using namespace std;
    typedef long long LL;
    LL f[50][20], bit[50], a, b;
    inline int ab(int x) { return x > 0 ? x : -x; }
    void init() {
    	bit[0] = 1; bit[1] = 10;
    	for(int i = 0;i <= 9;i ++) f[1][i] = 1;
    	for(int i = 2;i <= 20;i ++) {
    		bit[i] = bit[i-1] * 10;
    		for(int j = 0;j <= 9;j ++) {
    			for(int k = 0;k <= 9;k ++) {
    				if(ab(j-k) >= 2) f[i][j] += f[i-1][k];
    			}
    		}
    	}
    }
    LL calc(int x) {
    	LL pos, di = 1, res = 0, last = -1;
    	for(pos = 1;bit[pos] <= x;pos ++) {
    		for(int j = 1;j <= 9;j ++) {
    			res += f[pos][j];
    		}
    	}
    	for( ; pos ;pos --) {
    		int now = (x / bit[pos - 1]) % 10;
    		for(int j = di;j < now;j ++) {
    			if(ab(j-last) >= 2) res += f[pos][j];
    		}
    		if(ab(now-last) < 2) break;
    		di = 0; last = now;
    	}
    	return res;
    }
    int main() {
    	init();
    	cin >> a >> b;
    	cout << calc(b + 1) - calc(a) << endl;
    	return 0;
    }
    
  • 相关阅读:
    将空值转换为实际值
    图像的几何变换(一)
    图像的代数运算
    灰度直方图均衡化的算数推导
    图像的点运算
    探索数据可视化,业务数据是核心
    Gazebo機器人仿真學習探索筆記(一)安裝與使用
    脐带血要不要保存?看了你就明白!
    linuxsvn源代码版本库建立
    svn(subversion)代码版本管理在linux下的一些常见使用命令
  • 原文地址:https://www.cnblogs.com/Paranoid-LS/p/11343576.html
Copyright © 2020-2023  润新知