zoukankan      html  css  js  c++  java
  • Codeforces 55D Beautiful numbers(数位dp)

      题目大意:T(<=10)组数据,求[a,b]能够被其每个数位的数都整除的数(a,b<=9*10^18)

      这题差一点就想出来了,可是最后一步好难想也好妙啊

      首先这个数能够整除各个数位的lcm,而最大的lcm为2520(5*7*8*9)。我的想法是枚举lcm(记为lcmm),求出各个数位的lcm为lcmm且这个数能整除lcm的数有多少,dp[pos][val][lcm][lcmm]表示枚举lcmm,前pos位,这个数%lcmm为val,各个数位的lcm,然后实际上lcmm和lcm只有50个,所以后两维离散化就从2520->50了。但是我突然眉头一皱发现事情并不简单,pos最大为20,val最大为2520,lcm最大为50,lcmm最大为50,20*2520*50*50=126000000... QAQ滚去看题解

      设这个数为a,各数位为ai,lcm(ai)|a,lcm(ai)|2520,所以lcm(ai)|(a%2520)。这个怎么证呢?其实很简单。

      设lcm(ai)x=a,lcm(ai)y=2520,则(a%2520)=lcm(ai)x-lcm(ai)y*z=lcm(ai)(x-y*z),还是含有lcm(ai)。也就是说并不需要枚举lcmm,只要边dp边把val%2520就可以了...省了一维50,于是就巧妙的过了。

    代码如下:

    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #define ll long long
    using namespace std;
    ll dp[20][2550][50],a[20],l,r,num[2550],cnt,T;
    void read(ll &k)
    {
        k=0;ll f=1;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll dfs(int pos,int val,int lcm,bool limit)
    {
        if(pos==0)return val%lcm==0;
        if(!limit && dp[pos][val][num[lcm]]!=-1)return dp[pos][val][num[lcm]];
        int up=limit?a[pos]:9;
        ll ans=0;
        for(int i=0;i<=up;i++)
        ans+=dfs(pos-1,(val*10+i)%2520,i?(ll)lcm*i/gcd(lcm,i):lcm,limit && i==a[pos]);
        if(!limit)dp[pos][val][num[lcm]]=ans;
        return ans;
    }
    ll solve(ll x)
    {
        if(x==-1)return 0;
        int pos=0;
        while(x)
        {
            a[++pos]=x%10;
            x/=10;
        }
        ll ans=0;
        ans+=dfs(pos,0,1,1);
        return ans;
    }
    int main()
    {
        for(int i=1;i<=2520;i++)
        if(!(2520%i))num[i]=++cnt;
        memset(dp,-1,sizeof(dp));
        read(T);
        while(T--)read(l),read(r),printf("%lld
    ",solve(r)-solve(l-1));
    }
    View Code
  • 相关阅读:
    山屋惊魂 · 大模拟 · 码长破千 · 祭
    CSP-S 模拟92
    CSP-S 模拟91
    关于我
    CSP-S 模拟76
    [2020 年联考 A 卷] HEOI 2020 退役记
    csp-s 2019 退役记
    论人贵有自知之明的重要性
    [NOI2018] 你的名字
    HDU 3446 daizhenyang's chess
  • 原文地址:https://www.cnblogs.com/Sakits/p/6817532.html
Copyright © 2011-2022 走看看