zoukankan      html  css  js  c++  java
  • [SCOI2009] windy 数 (数位dp)

    题目

    算法

    应该是一道很经典的数位dp题
    我们设dp[i][j]是填到第i位此时第i位的数是j的方案数
    然后进行转移(代码注释)

    代码

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define ll long long
    using namespace std;
    ll p,q,dp[15][15];
    ll init(){//进行初始化 
       for(ll i = 0;i <= 9;i++) dp[1][i] = 1;//[0,9]显然都是windy数 
       for(ll i = 2;i <= 10;i++) 
       for(ll j = 0;j <= 9;j++)
       for(ll k = 0;k <= 9;k++)
       if(abs(j - k) >= 2) dp[i][j] += dp[i - 1][k];//先预处理好dp值 
    }
    ll work(ll x){//统计答案 
    	ll a[15],len = 0,ans = 0;
    	while(x){//将x分解 
    		a[++len] = x % 10;
    		x /= 10;
    	}
    	for(ll i = 1;i <= len - 1;i++)//先统计位数不足x位数的数 那这些数明显都可以计算到方案中 
    	for(ll j = 1;j <= 9;j++)
    	ans += dp[i][j];
    	for(ll i = 1;i < a[len];i++)//位数和x位数相同 但最高位比x最高位小 显然也可以 
    	ans += dp[len][i];
    	for(ll i = len - 1;i >= 1;i--){//这里处理位数和x位数相同 最高位 = x最高位的情况 
    	for(ll j = 0;j <= a[i] - 1;j++)
    	if(abs(j - a[i + 1])>= 2)  ans += dp[i][j];
    	if(abs(a[i + 1] - a[i]) < 2) break;
    	}
    	return ans;
    }
    ll a,b;
    int main(){
    	scanf("%lld%lld",&a,&b);
    	init();
    	cout<<work(b + 1) - work(a);//这里应用前缀和的思想 work计算[0,x)的方案数 那么用work(b + 1) - work(a) 就是[a,b]的方案数 
    }
    
  • 相关阅读:
    python 将字符串作为脚本运行
    Django Model获取字段名称并转为List存储
    django 过滤查询
    django 视图中异步执行python脚本
    python 异步执行python脚本
    django 筛选不等于的内容
    phpstorm中快速添加函数注释
    搜索模板elasticsearch
    laravel模型关联
    laravel关联用户
  • 原文地址:https://www.cnblogs.com/dixiao/p/13804892.html
Copyright © 2011-2022 走看看