zoukankan      html  css  js  c++  java
  • 洛谷P2657 [SCOI2009]windy数

    题目

    数位(DP)

    数位(DP)一般用于对满足一个什么条件的数的个数进行计数,且该数的数据范围很大的问题进行求解。这种题的状态一般都跟长度、限制条件、最高位上的数有关。

    本题的状态为:(dp[i][j])为长度为(i)的,最高位为(j)(windy)数个数。

    此状态有个非常简单的递推式,(dp[i][j]=sum{dp[i-1][k]}(abs(j-k)<=2))

    然后我们用函数(solv(a))返回(1)(a-1)的所有(windy)数的个数,最终答案即为(solv(b+1)-solv(a))的值。

    考虑(solv)函数该如何写,现将(a)逐位分解,求出(len)个数,然后将长度比(len)小无论最高位不为(0)的(因为不含前导零)(dp)值都加上,因为他们肯定都属于(1)(a-1)之中,然后再加上长度为(len)且最高位比(j)小的(windy)数个数,然后此时我们存在漏解的情况,我们还少长度为(len)且最高位跟(j)相同,但是又比(a)小的(windy)数个数,因为此时len为位是相同的,所以我们直接枚举len-1到1位,每次确定一位然后加上当前枚举位的dp值,如果当前位在枚举完了之后确定以后跟上一位相差小于二,则break,因为此位已确定且已经不满足条件了。

    //long long,inline后加函数类型
    //关键字:y1,time,tm,end,next,hash, j0,j1,jn,y0,yn,_end会re;
    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    long long A, B;
    int dp[1001][1001], temp[1001], len;//dp[i][j]代表长度i,最高位为j的windy数个数(注意是最高位)
    void init()
    {
    	for (int i = 0; i <= 9; i++)
    		dp[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)
    					dp[i][j] += dp[i - 1][k];
    }
    long long solv(int a)//返回n的数
    {
     	memset(temp, 0, sizeof(temp));
     	len = 0;
    	int ans = 0;
     	while (a)
     		temp[++len] = a % 10, a /= 10;
     	for (int i = 1; i <= len - 1; i++)//求len-1位的符合条件的windy数。 
     		for (int j = 1; j <= 9; j++)
     			ans += dp[i][j];
     	for (int j = 1; j < temp[len]; j++)
     		ans += dp[len][j];
     	for (int i = len - 1; i >= 1; i--)//求len-1所有跟a相差不大的数。 
     	{
     		for (int j = 0; j < temp[i]; j++)
     			if ( abs(j - temp[i + 1]) >= 2)
     				ans += dp[i][j];
     		if (abs(temp[i] - temp[i + 1]) < 2) break;//只要有一次相邻的两个数不满足则不需要再向下继续搜索下去了。 
     	}
     	return ans;
    }
    signed main()
    {
     	init();
     	scanf("%lld%lld", &A, &B);
     	printf("%lld",  solv(B + 1) - solv(A));
     	return 0;
    }
    
  • 相关阅读:
    poj 2104 C
    2015 百度之星初赛 1 2 2015ACM/ICPC亚洲区上海站 codeforces 851
    3.10补
    3.9补
    3.8补
    3.6补
    3.5补
    3.4补
    3.3补
    2.35补
  • 原文地址:https://www.cnblogs.com/liuwenyao/p/11820631.html
Copyright © 2011-2022 走看看