zoukankan      html  css  js  c++  java
  • 题解 P2657 【[SCOI2009]windy数】

    感觉数位DP有点弱,强化一下。。。


    这道题是一道比较裸的数位DP。

    我们用(dp[i][j])表示长度为(i)最高位为(j)的windy数有多少个,状态转移方程为(dp[i][j]=sum_{abs(j-k)>=2}{dp[i-1][k]})

    然后有一个小优化(其实不能算优化吧),就是算一下输入两个数的长度,然后取长度最大值作为第一维的极限,这样就稍微比直接算到(i=11)要优一点了。


    AC代码如下:

    28ms 788kb

    // By Ilverene
    
    #include<bits/stdc++.h>
    
    using namespace std;
    
    namespace StandardIO{
    
    	template<typename T>inline void read(T &x){
    		x=0;T f=1;char c=getchar();
    		for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
    		for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
    		x*=f;
    	}
    
    	template<typename T>inline void write(T x){
    		if(x<0)putchar('-'),x*=-1;
    		if(x>=10)write(x/10);
    		putchar(x%10+'0');
    	}
    
    }
    
    using namespace StandardIO;
    
    namespace Solve{
    	
    	// Define your global variables here.
    	int a,b;
    	int dp[11][11];
    	
    	// Define your main functions here.
    	template<typename T>inline T length(T num){
    		T ans=0;
    		for(;num;++ans,num/=10);
    		return ans;
    	}
    	
    	template<typename T>inline T calc(T limit){
    		memset(dp,0,sizeof(dp));
    		for(register int i=0;i<=9;++i){
    			dp[1][i]=1;
    		}
    		for(register int i=2;i<=limit;++i){
    			for(register int j=0;j<=9;++j){
    				for(register int k=0;k<=j-2;++k){
    					dp[i][j]+=dp[i-1][k];
    				}
    				for(register int k=j+2;k<=9;++k){
    					dp[i][j]+=dp[i-1][k];
    				}
    			}
    		}
    	}
    	
    	template<typename T>inline T calcAll(T n){
    		T len=0;
    		T num[11];
    		for(;n;num[++len]=n%10,n/=10);
    		T ans=0;
    		for(register int i=1;i<=len-1;++i){
    			for(register int j=1;j<=9;++j){
    				ans+=dp[i][j];
    			}
    		}
    		for(register int i=1;i<num[len];++i){
    			ans+=dp[len][i];
    		}
    		for(register int i=len-1;i>=1;--i){
    			for(register int j=0;j<=num[i]-1;++j){
    				if(abs(j-num[i+1])>=2)ans+=dp[i][j];
    			}
    			if(abs(num[i+1]-num[i])<2)break;
    		}
    		return ans;
    	}
    
    	inline void solve(){
    		// Write your main logic here.
    		read(a),read(b);
    		calc(max(length(a),length(b)));
    		write(calcAll(b+1)-calcAll(a));
    	}
    }
    
    using namespace Solve;
    
    int main(){
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	solve();
    }
    
    
  • 相关阅读:
    【LDAP】LDAP 中 CN, OU, DC 的含义
    【LDAP】LDAP介绍
    【LDAP】Openldap导入数据
    【LDAP】LDAP常用命令解析
    【Linux】debian 7 安装 rz sz lrzsz
    【Linux】Debian 8 设置命令行界面的文本颜色
    【Linux】Debian vim没有颜色的解决办法
    【计算机网络】一步一步学习IP路由流程
    【密码学】RSA密钥长度、明文长度和密文长度
    【密码学】CSP的概念
  • 原文地址:https://www.cnblogs.com/ilverene/p/9850555.html
Copyright © 2011-2022 走看看