[bzoj3679]數字之積

很容易看出來是數位dp
我們可以發現個位數字乘積的取值並沒有特別多,於是可以通過質因數只有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));
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章