• [CF55D] Beautiful numbers


    Description

    给定 ([l,r]),求 ([l,r]) 之间有多少个数满足它的任意数位都可以整除它本身。

    Solution

    (f(i,j,k,full)) 表示从高到低考虑到第 (i) 位数,前面构成的数模 (2520=j),前面这些数位的 (LCM)(k),当前是否贴合上界的方案数。把 (k) 离散化一下节约空间。

    注意只需要记录 full=0 的情况即可,并且这些情况可以在各组数据间复用,因此就要求 (i) 要倒着记录。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    const int N = 1000005;
    
    
    vector <int> a;
    int mp[2525],imp[2525];
    int f[20][2520][50],n;
    int gg[55][55];
    int CNT;
    
    int gcd(int p,int q)
    {
        p=mp[p];
        q=mp[q];
        if(!(~gg[p][q]))
        {
            ++CNT;
            return gg[p][q]=__gcd(imp[p],imp[q]);
        }
        else 
        {
            return gg[p][q];
        }
    }
    
    int lcm(int p,int q)
    {
        if(p==0) return q;
        if(q==0) return p;
        return p*q/gcd(p,q);
    }
    
    
    int calc(int i,int j,int k,int full)
    {
        CNT++;
        if(i<0) return j%imp[k]==0; 
        if(!full && ~f[i][j][k]) return f[i][j][k];
        int lim=full?a[i]:9;
        int ans=0;
    
        for(int now=0;now<=lim;now++)
        {
            int newj=(j*10+now)%2520;
            int newk=mp[lcm(now,imp[k])];
            ans+=calc(i-1,newj,newk,full&&now==lim);
        }
        if(!full) return f[i][j][k]=ans;
        else return ans;
    }
    
    int solve(int n)
    {
        int ans=0;
        a.clear();
        // memset(f,-1,sizeof f);
        while(n)
        {
            a.push_back(n%10);
            n/=10;
        }
        ::n=a.size();
        if(a.size()==0) return 1;
        // reverse(a.begin(),a.end());
        int tmp = calc(::n-1,0,1,1);
        return tmp;
    }
    
    void doit()
    {
        int l,r;
        cin>>l>>r;
        cout<<solve(r)-solve(l-1)<<endl;
    }
    
    signed main()
    {
        
        ios::sync_with_stdio(false);
        
        int ind=0;
        for(int i=1;i<=2520;i++)
        {
            if(2520%i==0)
            {
                mp[i]=++ind;
                imp[ind]=i;
            }
        }
        memset(gg,-1,sizeof gg);
        memset(f,-1,sizeof f);
        int t;
        cin>>t;
        while(t--)
        {
            doit();
        }
    
        // cout<<CNT<<endl;
    }
    
  • 相关阅读:
    JS Table排序类
    JavaScript使用技巧精萃
    修改鄒建 老師的SQL PivotTable,增加同分組非交叉欄位
    类似gmail添加附件
    [转贴]Js中 关于top、clientTop、scrollTop、offsetTop等
    Three Tier Code generation with Codesmith
    SQL中取得漢字拼音首字母或五筆首鍵編碼
    (转)ComputerStyle与currentStyle的区别
    html css样式色彩解析
    js 拖拽效果
  • 原文地址:https://www.cnblogs.com/mollnn/p/14018624.html
Copyright © 2020-2023  润新知