zoukankan      html  css  js  c++  java
  • [bzoj1026][SCOI2009]windy数_数位dp

    windy数 bzoj-1026

        题目大意:求一段区间中的windy数个数。

        注释:如果一个数任意相邻两位的差的绝对值都不小于2,这个数就是windy数,没有前导0。$区间边界<=2cdot 10^9$。

          想法:数位dp裸题,何为数位dp?

          数位dp的意思就是我们交换一种dp的方式。通过数位进行dp。数位dp的主旨分为两点:1.对于所求答案的预处理。2.对于所求区间的边界特判。我们对于数位dp有几个显而易见但是却比较useful的性质:

            如果一个数的位数小于第二个数的位数,那么后者是大于前者的。

            如果两个数的位数相等且前者的最高位是小于后者的最高位的,那么后者是大于前者的。

            如果将两个数同时加减同一个数,他们之间的大小关系显然是不变的。

          通过以上几个性质,我们在枚举边界时可以先将位数小的全部枚举,然后对于高位到低位依次dp。

          回到这道题,我们先设状态dp[i][j]表示i位数且最高位为j。在转移时,我们其实很容易想到

            $sumlimits_{k=0}^{9}dp(i-1,k)cdot [|j-k|ge 2]$

          之后,关于边界的处理,看代码... ...

        最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    typedef long long ll;
    using namespace std;
    int f[20][20];
    void before_hand()//这个是预处理,在上面说的很清楚了
    {
    	memset(f,0,sizeof f);
    	for(int i=0;i<=9;i++) f[1][i]=1;
    	for(int i=2;i<=10;i++) for(int j=0;j<=9;j++) for(int k=0;k<=9;k++)
    	{
    		if(abs(j-k)>=2) f[i][j]+=f[i-1][k];
    	}
    }
    int dig[20];
    ll dispose(ll x)//对边界的处理
    {
    	int ans=0;
    	int k=0;
    	memset(dig,0,sizeof dig);
    	if(!x) return 0;
    	while(x)
    	{
    		dig[++k]=x%10;
    		x/=10;
    	}
    	for(int i=1;i<=k-1;i++)	for(int j=1;j<=9;j++)//我们用给出的第一条性质,发现
    		ans+=f[i][j];//ans这时一定是被所求答案覆盖的
    	for(int i=1;i<dig[k];i++)//第二个性质
    		ans+=f[k][i];
    	for(int i=k-1;i>=1;i--)//反复运用第二、三个性质
    	{
    		for(int j=0;j<dig[i];j++)
    		{
    			if(abs(j-dig[i+1])>=2) ans+=f[i][j];
    		}
    		if(abs(dig[i+1]-dig[i])<2) break;
    		if(i==1) ans++;
    	}
    	return ans;
    }
    int main()
    {
    	ll l,r;
    	scanf("%lld%lld",&l,&r);
    	before_hand();
    	printf("%lld
    ",dispose(r)-dispose(l-1));
    	return 0;
    }
    

         小结:前面预处理的边界不要忘记特判。数位dp的第一道题,加油,JZYshuraK

  • 相关阅读:
    Python和C#基本算法实现对比
    数据库并发
    NetCore 启动地址配置详解
    SkyWalking Liunx 环境搭建&NetCore接入
    Autofac踩坑经历
    centos 7 安装elasticsearch
    centos 7 java1.8安装
    AppDomin学习与分享
    .Net 程序代码混淆加密工具 ILProtector
    c# 重新认识 Double 浮点型
  • 原文地址:https://www.cnblogs.com/ShuraK/p/8550880.html
Copyright © 2011-2022 走看看