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

    [Description]

    美丽数是指能被它的每一位非0的数字整除的正整数。


    [Input]

    包含若干组数据,每组数据一行两个数n,m,表示求[n,m]之间的美丽数的个数。


    [output]

    对于每组数据输出一个答案,各占一行。

    Input
    1
    1 9
    Output
    9
    Input
    1
    12 15
    Output
    2

    [Hit]

    0 < n , m < 10^18

    测试数据不超过100

     

     

     

    基本思路是用:dp[len][mod][lcm]表示<=len的长度中,此数为mod,各数位的最小公倍数为lcm的数的个数来进行记忆化搜索。方法和上一题类似。

     

    但我们发现,len[1,20]范围内,mod[1,1^18]范围内,lcm[1,2520]范围内。所以dp数组肯定超内存。

     

    下面我们来进行内存优化:

     

    假设这个数为a,各个数位的值分别为ai,那么我们发现lcm(ai) | a.

     

    [1,9]的最小公倍数是2520.那么lcm(ai) | 2520, 所以lcm(ai) | (a%2520).

     

    所以第二维大小我们可以从1^18降到2520,方法是%2520.

     

    现在的dp数组的内存是20*2520*2520,还是很大。

     

    然后我们再考虑:

     

    我们发现某一个数的各个数位的数的最小公倍数最大是2520,而且只能是2520的公约数。而2520的公约数有48个。所以第三维我们只用[50]的空间就行了。

     

    方法是用Hash进行离散化。‘

     

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 typedef long long lol;
     7 int bit[21],ha[2520],len,cnt;
     8 lol f[21][2521][51],ans;
     9 int gcd(int x,int y)
    10 {
    11     if (!y) return x;
    12     return gcd(y,x%y);
    13 }
    14 int lcm(int x,int y)
    15 {
    16     return x*y/gcd(x,y);
    17 }
    18 void has(int x,int l)
    19 {
    20     if (x>10) return;
    21     if (ha[l]==0) 
    22     ha[l]=++cnt; 
    23     has(x+1,lcm(l,x));
    24     has(x+1,l);
    25 }
    26 lol dfs(int pos,int pre_num,int pre_lcm,bool flag)
    27 {int nxt_num,nxt_lcm,r,i;
    28   lol s=0;
    29     if (pos==0) 
    30     return pre_num%pre_lcm==0;
    31     if (flag&&f[pos][pre_num][ha[pre_lcm]]!=-1)
    32     return f[pos][pre_num][ha[pre_lcm]];
    33     if (flag) r=9;
    34     else r=bit[pos];
    35     for (i=0;i<=r;i++)
    36     {
    37         nxt_num=pre_num*10+i;
    38         nxt_num%=2520;
    39         if (i)
    40         nxt_lcm=lcm(pre_lcm,i);
    41         else nxt_lcm=pre_lcm;
    42         s+=dfs(pos-1,nxt_num,nxt_lcm,flag||(i<r));
    43     }
    44     if (flag)
    45     f[pos][pre_num][ha[pre_lcm]]=s;
    46     return s;
    47 }
    48 lol solve(lol x)
    49 {
    50     len=0;
    51     while (x)
    52     {
    53         len++;
    54         bit[len]=x%10;
    55         x/=10;
    56     }
    57     return dfs(len,0,1,0);
    58 }
    59 int main()
    60 {lol l,r;
    61 int T;
    62     cin>>T;
    63     has(2,1);
    64     memset(f,-1,sizeof(f));
    65     while (T--)
    66     {
    67         scanf("%I64d%I64d",&l,&r);
    68         ans=solve(r)-solve(l-1);
    69     printf("%I64d
    ",ans);
    70     }
    71 }

     

     

     

  • 相关阅读:
    重复的listen port引发的问题
    Win10开始运行不保存历史记录原因和解决方法
    意识到const版本函数的重要性
    人物访谈1
    人物访谈2
    读《浪潮之巅》有感
    测试作业
    读《活出生命的意义》有感
    价值观作业
    关于C语言的问卷调查
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7467463.html
Copyright © 2011-2022 走看看