zoukankan      html  css  js  c++  java
  • CodeForces 55D Beautiful numbers

    题目链接:http://codeforces.com/problemset/problem/55/D

    题意:一个数如果能够被她的每一个非0位整除,那么这个数就叫做Beautiful numbers。

    给出l和r,问区间[l,r]中总共有多少个Beautiful numbers。

    思路:

    题意即这个数要能够被它的每个非0位的最小公倍数整除。

    因为每一位最多就是1,2,3,4,5,6,7,8,9。也就是这个数最坏的情况要能够被1*2*3*4*5*6*7*8*9 = 2520整除。

    设这个数为x,设x = 2520*t+y。设lcm为x每个非0位出现的数的最小公倍数。

    那么可以知道2520 % lcm = 0。

    所以x % lcm = x%2520%lcm。所以在记忆化搜索的时候只要保存当前数%2520的余数就可以了。

    所以需要一个dp[cur][last][lcm] 大小有19*2520*2520要超内存,所以要把记录的lcm离散化一下。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 long long l, r;
     4 int num[22];
     5 int Hash[2550];
     6 long long dp[22][2530][50];
     7 void init()
     8 {
     9     memset(dp, -1, sizeof(dp));
    10     int cnt = 0;
    11     Hash[0] = 0;
    12     for(int i = 1; i <= 2520; i++)
    13     {
    14         if(2520%i == 0) Hash[i] = ++cnt;
    15     }
    16 }
    17 
    18 int gcd(int a, int b)
    19 {
    20     if(a < b) return gcd(b, a);
    21     if(b == 0) return a;
    22     return gcd(b, a%b);
    23 }
    24 int getlcm(int a, int b)
    25 {
    26     return a/gcd(a,b)*b;
    27 }
    28 long long dfs(int cur, int last, int lcm, int limit)
    29 {
    30     if(cur < 0)
    31     {
    32         if(last % lcm == 0) return 1;
    33         else return 0;
    34     }
    35     if(!limit && dp[cur][last][Hash[lcm]] != -1) return dp[cur][last][Hash[lcm]];
    36     
    37     long long ret = 0;
    38     int up = limit?num[cur]:9;
    39     for(int i = 0; i <= up; i++)
    40     {
    41         int temp = (last*10+i)%2520;
    42         int nowlcm;
    43         if(i != 0) nowlcm = getlcm(lcm, i);
    44         else nowlcm = lcm;
    45         ret += dfs(cur-1, temp, nowlcm, limit && i == up);
    46     }
    47     if(!limit) dp[cur][last][Hash[lcm]] = ret;
    48     return ret;
    49 }
    50 long long slove(long long x)
    51 {
    52     int cnt = 0;
    53     while(x)
    54     {
    55         num[cnt++] = x % 10;
    56         x /= 10;
    57     }
    58     return dfs(cnt-1, 0, 1, 1);
    59 }
    60 int T;
    61 int main() 
    62 {
    63     init();
    64     scanf("%d", &T);
    65     while(T--)
    66     {
    67       cin>>l>>r;
    68       cout<<slove(r) - slove(l-1)<<endl;
    69     }
    70     return 0;
    71 }
  • 相关阅读:
    svn的使用
    补间动画和属性动画
    图片的处理
    在Android中来修改SQL里面的权限和显示内容
    两种Service如何一起使用
    HDU-1083
    HDU 2444
    HDU-1045 Fire Net
    hrbust
    UVA
  • 原文地址:https://www.cnblogs.com/titicia/p/5234784.html
Copyright © 2011-2022 走看看