1. 程式人生 > >1026 windy數

1026 windy數

給兩個數1 <= a <= b <= 2e9,求他們之間的windy數的個數

windy數定義:不含前導零且相鄰兩個數字之差至少為2的正整數被稱為windy數。

這題用數位dp來做

定義:dp[i][j]:第i位數字為j,並且滿足情況數的個數.

那麼狀態轉移方程為

dp[i][j] = ∑dp[i−1][k] (abs(k−j) >= 2)

最後用差分搞一搞,solve(b + 1) - solve(a)就是a, b之間滿足情況的個數了(solve(x)表示小於x的滿足條件的個數)

“注意一下dp細節即可”

咳咳還是說一下dp的細節:

初始化為0,不談。

dp[1][i]初始化為1,這是處理只有一位的情況

然後對於2-11位,列舉這一位的數字j,對於這個j,列舉它的前面一位數字為k,滿足abs(k - j) >= 2就更新

dp[i][j] += dp[i-1][k]

好啦,dp陣列初始化好了,對於一個數n,如何求小於它的滿足條件的數的個數呢

比如一個數是四位的

首先加上三位的所有情況,再加上第四位1-(num[4] - 1)的所有情況

以上這些情況都是能嚴格保證小於所給的數的

所以要特殊對待一下第四位就是所給的數的第四位的時候

從高位往地位遍歷,如果相差可以大於2的話就加上這個位置的答案,並且一旦碰到給出的相差就小於2,直接break

(因為你往下不能改了)

最後很容易發現所給的數本身是沒有判斷的,所以算出來的是小於這個數的答案

說的不太清楚,反正我是理解了,嘻嘻

#pragma GCC diagnostic error "-std=c++11"
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII  pair<int, int> 
#define all(x) x.begin(), x.end()
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;
#define int ll

int dp[12][10];
int num[12];

void init(){
	memset(dp, 0, sizeof(dp));
	for(int i = 0; i <= 9; i++) dp[1][i] = 1;
	for(int i = 2; i <= 11; 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];
			}
		}
	}
}

int solve(int n){
	int cnt = 0, sum = 0;
	while(n){
		num[++cnt] = n % 10;
		n /= 10;
	}
	num[cnt+1] = 0;
	for(int i = 1; i < cnt; i++){
		for(int j = 1; j <= 9; j++){
			sum += dp[i][j];
		}
	}
	for(int i = 1; i < num[cnt]; i++) sum += dp[cnt][i];
	for(int i = cnt - 1; i >= 1; i--){
		for(int j = 0; j <= num[i] - 1; j++){
			if(abs(num[i+1] - j) >= 2) sum += dp[i][j];
		}
		if(abs(num[i+1] - num[i]) < 2) break;
	}
	return sum;
}

int32_t main()
{
	init();
	ll a, b;
	scanf("%lld %lld", &a, &b);
	printf("%lld\n", solve(b + 1) - solve(a));
	return 0;
}