100道codeforces 2500

复制代码
首先小小容斥一下,用1~r的减去1~l-1的。
1~r的,可以想到数位dp
设f[len][pre][mod]表示从低位数第len位,当前数字的值%2450为pre,当前用过的数字的lcm为mod的方案数
使用limit表示是否贴着上界
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;//1e9+7
ll read(){ll x;scanf("%lld",&x);return x;}
ll quick(ll a,ll b){ll t=1;while(b){if(b&1)t=t*a%mod;b=b/2;a=a*a%mod;}return t;}
int lowbit(int x){return x&(-x);}
int digit[20],mp[2521];
ll f[20][2521][50];
ll dfs(int len,int pre,int mod,int limit)
{
    if(!len)
        return pre%mod==0;
    if(!limit&&f[len][pre][mp[mod]]!=-1)
        return f[len][pre][mp[mod]];
    ll ret=0;
    int ed=limit?digit[len]:9;
    for(int i=0;i<=ed;i++)
        ret+=dfs(len-1,(pre*10+i)%2520,i==0?mod:mod/__gcd(mod,i)*i,limit&&i==ed);
    if(!limit)
        f[len][pre][mp[mod]]=ret;
    return ret;
}
ll ask(ll x)
{
    int len=0;
    while(x)
    {digit[++len]=x%10;x=x/10;
    }
    return dfs(len,0,1,1);
}
void work()
{
    memset(f,-1,sizeof(f));
    ll l=read(),r=read();
    cout<<ask(r)-ask(l-1)<<'\n';
}
int main()
{
    int cnt=0;
    for(int i=1;i<=2520;i++)
        if(2520%i==0)
            mp[i]=++cnt;
    for(int t=read();t;t--)
        work();
}
55D
复制代码

 

posted @   zzuqy  阅读(0)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示