文明大学生

数学公式

Beautiful numbers CodeForces - 55D

#include<string>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn=2550;
//原数是不是整除非零位,也就是整除最小公倍数,1-9所有最小公倍数为2520
int a[20],mp[maxn];//1-9任意最小公倍数是48个
ll d[20][maxn][50];//第几位,取模后为sum,最小公倍数为lcm的个数
ll n,m;
void init()
{
    int ans=0;
    for(int i=1; i<=2520; i++)
        if(2520%i==0)
        {
            mp[i]=ans;
            ans++;
        }
}
ll work(ll x,ll y)
{
    if(x==0||y==0)
        return x+y;
    else
        return x*y/__gcd(x,y);
}
ll dfs(int pos,ll sum,int lcm,bool limit)
{
    if(pos==-1)
    {
        return (sum%lcm)==0;
    }
    if(!limit&&d[pos][sum][mp[lcm]]!=-1)
        return d[pos][sum][mp[lcm]];
    int u=limit?a[pos]:9;
    ll temp=0;
    for(int i=0; i<=u; i++)
    {
        temp+=dfs(pos-1,(sum*10+i)%2520,work(lcm,i),limit&&a[pos]==i);
    }
    if(!limit)
        d[pos][sum][mp[lcm]]=temp;
    return temp;
}
ll solve(ll x)
{
    int pos=0;
    while(x>0)
    {
        a[pos++]=int(x%10);
        x/=10;
    }
    return dfs(pos-1,0,1,true);//必须为1,否则sum%lcm报错
}
int main()
{
    memset(d,-1,sizeof d);
    init();
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        cout<<(solve(m)-solve(n-1))<<endl;
    }
    return 0;
}

 

posted on 2020-03-09 12:53  文明大学生  阅读(126)  评论(0编辑  收藏  举报

导航