zoukankan      html  css  js  c++  java
  • CF 55D Beautiful Numbers

    Description

    求$[L, R]$内, 有多少个数能被自己所有位上的数整除

    Solution

    妥妥的数位DP, 但是就是不会做2333, 状态很难想到。

    显然不可能把最后的数作为一个状态。

    我们想到一个数如果整除所有位上的数, 肯定整除他们的最小公倍数, 所以把所有位上的数的最小公倍数作为一个状态。

    然后我们发现$1~9$的最小公倍数只有$2520$, 所以只要$%上2520$作为一个状态, 到最后的时候仍然能够判断一个数是否被最小公倍数整除。

    所以$sum[pos][lcm][mod]$ 为状态进行数位DP即可

    Code

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<map>
     5 #define rd read()
     6 #define ll long long
     7 #define R register 
     8 using namespace std;
     9 
    10 const int mod = 2520;
    11 
    12 int T, a[25];
    13 ll n, m, sum[20][50][mod + 10];
    14 int tot, b[300], vis[3000];
    15 
    16 ll read() {
    17     R ll X = 0; R int p = 1; R char c = getchar();
    18     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
    19     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
    20     return X * p;
    21 }
    22 
    23 int fd(int x) {
    24     return lower_bound(b + 1, b + 1 + tot, x) - b;
    25 }
    26 
    27 int gcd(int x, int y) {
    28     return x % y ? gcd(y, x % y) : y;
    29 }
    30 
    31 ll dfs(int pos, int lcm, int mo, bool lim) {
    32     if(!pos) return mo % b[lcm] ? 0 : 1;
    33     if(!lim && sum[pos][lcm][mo] != -1) return sum[pos][lcm][mo];
    34     int up = lim ? a[pos] : 9;
    35     ll tmp = 0, nxt;
    36     for(int i = 0; i <= up; ++i) {
    37         nxt = (b[lcm] * (i ? i : 1)) / gcd(b[lcm], i? i : 1);
    38         tmp += dfs(pos - 1, fd(nxt), (mo * 10 + i) % mod, lim && a[pos] == i);
    39     }
    40     if(!lim) sum[pos][lcm][mo] = tmp;
    41     return tmp;
    42 }
    43 
    44 ll work(ll x) {
    45     int len = 0;
    46     while(x) {
    47         a[++len] = x % 10;
    48         x /= 10;
    49     }
    50     return dfs(len, 1, 0, true);
    51 }
    52 
    53 void sec(int dep, int lcm) {
    54     if(!vis[lcm]) b[++tot] = lcm, vis[lcm] = 1;
    55     if(dep == 10) return;
    56     sec(dep + 1, lcm);
    57     sec(dep + 1, (lcm * dep) / gcd(lcm, dep));
    58 }
    59 
    60 void init() {
    61     sec(1, 1);
    62     sort(b + 1, b + 1 + tot);
    63     memset(sum, -1, sizeof(sum));
    64 }
    65 
    66 int main()
    67 {
    68     T = rd;
    69     init();
    70     for(; T; T--) {
    71         ll l = rd, r = rd;
    72         printf("%lld
    ", work(r) - work(l - 1));
    73     }
    74 }
    View Code
  • 相关阅读:
    java encoding
    [转]shell 变量的作用域
    [转] shell :解析json的命令-jq
    [转] Linux user-space Atomic Operations && GCC Atomic builtins
    [转]reference counting
    [转]memory order,memory barrier,原子操作
    [转]c语言volatile 关键字
    OCF介绍
    [转]计算机存储 cache介绍
    [转] linux IO
  • 原文地址:https://www.cnblogs.com/cychester/p/9630423.html
Copyright © 2011-2022 走看看