【数位DP】【P2657】[SCOI2009]windy数


Description

windy定义了一种windy数。不含前导零且相邻两个数字之差至少为 \(2\) 的正整数被称为windy数。 windy想知道,

\(A\)\(B\) 之间,包括 \(A\)\(B\),总共有多少个windy数?

Limitation

\(1 \leq A \leq B \leq 2000000000\)

Solution

前天重写这个题,换了一种比较好写的DP方式,这里记下来。

考虑由于前导 \(0\) 和顶上界都最多可能有 \(1\) 中方案,因此直接使用一个 bool 变量记录即可。

\(f_{i, j}\) 是考虑前 \(i\) 位,第 \(i\) 位是 \(j\)不顶上界的方案数,这样的转移就非常好写了。、

Code

#include <cmath>
#include <cstdio>
#include <cstring>

const int maxn = 100;

int x, y;
int A[maxn], B[maxn];
ll frog[maxn][10];

int ReadNum(int *p);
ll calc(const int *const num, const int n);

int main() {
  freopen("1.in", "r", stdin);
  int x = ReadNum(A); y = ReadNum(B);
  for (int i = x - 1; ~i; --i) {
    if ((--A[i]) >= 0) {
      break;
    } else {
      A[i] = 9;
    }
  }
  if (A[x] == 0) { --x; }
  qw(calc(B, y) - calc(A, x), '\n', true);
  return 0;
}

int ReadNum(int *p) {
  auto beg = p;
  do *p = IPT::GetChar() - '0'; while ((*p < 0) || (*p > 9));
  do *(++p) = IPT::GetChar() - '0'; while ((*p >= 0) && (*p <= 9));
  return p - beg;
}

ll calc(const int *const num, const int n) {
  if (n <= 1) {
    return num[0];
  }
  memset(frog, 0, sizeof frog);
  bool upc = true;
  for (int i = 1; i < num[0]; ++i) {
    frog[0][i] = 1;
  }
  for (int i = 1; i < n; ++i) {
    int di = i - 1;
    for (int j = 0; j < 10; ++j) {
      for (int k = 0; k < 10; ++k) if (abs(j - k) >= 2) {
        frog[i][j] += frog[di][k];
      }
      ++frog[i][j];
    }
    --frog[i][0];
    if (upc) {
      for (int k = 0; k < num[i]; ++k) if (abs(num[di] - k) >= 2) {
        ++frog[i][k];
      }
      if (abs(num[di] - num[i]) < 2) {
        upc = false;
      }
    }
  }
  ll _ret = 0;
  for (int i = 0, dn = n - 1; i < 10; ++i) {
    _ret += frog[dn][i];
  }
  return _ret + upc;
}
优质内容筛选与推荐>>
1、年轻的希望
2、一个界面很不错的blog网站
3、WCF 第十章 异常处理 实现客户端错误处理器
4、构造函数中base与this的区别
5、解决-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable and mvn script match.


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号