zoukankan      html  css  js  c++  java
  • 洛谷 P2657

    题目大意

    不含前导零且相邻两个数字之差至少为 (2) 的正整数被称为 (windy) 数。 (windy) 想知道,在 (l)(r) 之间,包括 (l)(r) ,总共有多少个 (windy) 数?

    solution

    有一个显而易见的结论

    我们发现 (ans_{l, r} = ans_{1. r} - ans_{1, l - 1})

    那我们只需要处理 (1 - r) 的即可

    那我们就可以来推我们的状态转移方程了

    我们设 (f_{i, j}) 是长度 (i) , 最高位是 (j) 的个数

    (f_{i, j} += f_{i - 1, k}, | j - k | geqslant 2)

    对于(ans_{1, r}) 我们可以采用以下策略 :

    (len)(r) 的位数, (a_{len})(r) 的每一位

    1. 对于所有长度小于 (len)(f) , (res += f_{i, j}, i in [1, len - 1], j in [1, 9])
    2. 对于长度等于 (len)且最高位小于 (a_{len})(f) , (res += f_{len, j}, j in [1, a_{len}))
    3. 然后对于剩下的 (len - 1) 位, 我们继续执行 (2) 操作, 不过 (jin [0, a_i)) (因为最高位已经不为0了)

    答案就是 (ans_{1, r} - ans_{1, l - 1})

    Code:

    #include <cstdio>
    #include <iostream>
    #include <string>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <queue>
    
    #define int long long
    #define rr register
    
    #define MAXN 2100
    #define MAXM 100010
    #define inf 1e18
    
    using namespace std;
    
    const int mod = 998244353;
    
    inline int read() {
    	int s = 0, f = 0;
    	char ch = getchar();
    	while (!isdigit(ch)) {f |= ch == '-'; ch = getchar();}
    	while (isdigit(ch)) {s = s * 10 + (ch ^ 48); ch = getchar();}
    	return f ? -s : s;
    }
    
    int A, B;
    
    int a[20];
    
    int f[20][20];
    
    inline void init() {
    	for (rr int i = 0; i <= 9; i++) f[1][i] = 1;
    	for (rr int i = 2; i <= 10; i++)
    		for (rr int j = 0; j <= 9; j++)
    			for (rr int k = 0; k <= 9; k++)
    				if (abs(j - k) >= 2) f[i][j] += f[i - 1][k];
    }
    
    inline int work(int x) {
    	memset(a, 0, sizeof a);
    	int len = 0, ans = 0;
    	while (x) {
    		a[++len] = x % 10;
    		x /= 10;
    	}
    	for (rr int i = 1; i <= len - 1; i++)
    		for (rr int j = 1; j <= 9; j++)
    			ans += f[i][j];
    	for (rr int i = 1; i < a[len]; i++)
    		ans += f[len][i];
    	for (rr int i = len - 1; i >= 1; i--) {
    		for (rr int j = 0; j < a[i]; j++)
    			if (abs(j - a[i + 1]) >= 2) ans += f[i][j];
    		if (abs(a[i + 1] -a[i]) < 2) break;
    	}
    	return ans;
    }
    
    signed main() {
    	init();
    	A = read();
    	B = read();
    	cout << work(B + 1) - work(A);
    }
    
  • 相关阅读:
    dubbo源码阅读-服务调用之远程调用(十二)
    dubbo源码阅读-注册中心(十三)之Zookeeper
    dubbo源码阅读-远程暴露(七)之Transport
    dubbo源码阅读-远程暴露(七)之Exchangers
    dubbo源码阅读-服务调用(十二)之本地调用(Injvm)
    dubbo源码阅读-ProxyFactory(十一)之StubProxyFactoryWrapper本地存根
    dubbo源码阅读-服务暴露(七)之本地暴露(Injvm)
    dubbo源码阅读-ProxyFactory(十一)之JavassistFactory
    OpenCV 实现颜色直方图
    FFMPEG结构体分析:AVPacket
  • 原文地址:https://www.cnblogs.com/lieberdq/p/13983457.html
Copyright © 2011-2022 走看看