[bzoj3679]数字之积

很容易看出来是数位dp
我们可以发现个位数字乘积的取值并没有特别多,于是可以通过质因数只有 2,3,5,7 2 , 3 , 5 , 7 的性质预处理出每种乘积,可以用map存起来。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int p[4]={2,3,5,7};
map<int,int> m;
int pt[5211];
ll f[21][5211],n,a,b,tot,c[21];
inline void dfs(ll s,ll st){
    for(int i=st;i<4;++i){
        if(s*p[i]>n) break;
        m[s*p[i]]=++tot;
        pt[tot]=s*p[i];
        dfs(s*p[i],i);
    }
}
ll solve(ll x){
    if(x==0) return 0;
    ll res=0,l=0,s;
    while(x) c[++l]=x%10,x/=10;
    for(int j=1;j<l;++j)
    for(int i=1;i<=tot;++i)
    if(pt[i]<=n) res+=f[j][i];
    s=c[l];
    for(int i=1;i<c[l];++i)
    for(int j=1;j<=tot;++j)
    if(i*pt[j]<=n) res+=f[l-1][m[pt[j]]];
    for(int i=l-1;i>=2;--i){
        for(int k=1;k<c[i];++k)
        for(int j=1;j<=tot;++j)
        if(s*k*pt[j]<=n) res+=f[i-1][m[pt[j]]];
        s*=c[i];if(!s||s>n) break;
    }
    for(int i=1;i<=c[1];++i)
    if(s*i<=n&&s*i) ++res;
    return res;
}
int main(){
    scanf("%d%lld%lld",&n,&a,&b);
    m[1]=++tot;pt[tot]=1;dfs(1,0);
    for(int i=1;i<=9&&i<=n;++i) f[1][m[i]]=1;
    for(int i=1;i<=17;++i)
    for(int j=1;j<=tot;++j)
    for(int k=1;k<=9;++k) f[i+1][m[pt[j]*k]]+=f[i][j];
    return !printf("%lld",solve(b-1)-solve(a-1));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值