我们会发现对于一个乘积一定可以分解为2 3 5 7的倍数
然后就根据这个来做了预处理出每个数的幂次
总感觉数位DP用记忆化搜索更方便?
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#define ll long long
using namespace std;
char c;
inline void read(ll &a)
{
a=0;do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
ll Pow3[1001];
ll Pow2[1001];
ll Pow5[1001];
ll Pow7[1001];
ll n;
const
ll Mod=102367;
struct Rec
{
ll x,cnt2,cnt3,cnt5,cnt7,res;
inline ll Hash(){return ((x+cnt2*177+cnt3*2333+cnt5*6787+cnt7*323+res*641)%Mod+Mod)%Mod;}
inline friend bool operator !=(Rec a,Rec b)
{
return (a.x^b.x)|(a.res^b.res)|(a.cnt2^b.cnt2)|(a.cnt3^b.cnt3)|(a.cnt5^b.cnt5)|(a.cnt7^b.cnt7);
}
};
struct Hash
{
Rec Key;
ll Ans;
Hash*next;
}*Table[Mod];
ll Ans;
inline bool Find(Rec Key,Hash *Cur)
{
if(Cur==NULL)return false;
if(Key!=Cur->Key)return Find(Key,Cur->next);
Ans=Cur->Ans;
return true;
}
inline void Insert(int Pl,Rec Key,ll Ans)
{
Hash *tp=new Hash;
tp->next=Table[Pl];
tp->Ans=Ans;
tp->Key=Key;
Table[Pl]=tp;
}
int f,k;
ll F(ll x,ll cnt2,ll cnt3,ll cnt5,ll cnt7,ll res,bool R)
{
Rec tp;
ll t;
if(Pow2[cnt2]*Pow3[cnt3]*Pow5[cnt5]*Pow7[cnt7]>n)return 0;
if(x==0)
return 1;
tp.cnt2=cnt2,tp.cnt3=cnt3,tp.cnt5=cnt5,tp.cnt7=cnt7,tp.res=res,tp.x=x;
if(R)tp.res=-1;
if(Find(tp,Table[t=tp.Hash()]))return Ans;
ll Ans=0;
if(res>=x*1)
{
Ans+=F(x/10,cnt2,cnt3,cnt5,cnt7,res-x,R||(res>=2*x));
}
if(res>=x*2)
{
Ans+=F(x/10,cnt2+1,cnt3,cnt5,cnt7,res-2*x,R||(res>=3*x));
}
if(res>=x*3)
{
Ans+=F(x/10,cnt2,cnt3+1,cnt5,cnt7,res-3*x,R||(res>=4*x));
}
if(res>=x*4)
{
Ans+=F(x/10,cnt2+2,cnt3,cnt5,cnt7,res-4*x,R||(res>=5*x));
}
if(res>=x*5)
{
Ans+=F(x/10,cnt2,cnt3,cnt5+1,cnt7,res-5*x,R||(res>=6*x));
}
if(res>=x*6)
{
Ans+=F(x/10,cnt2+1,cnt3+1,cnt5,cnt7,res-6*x,R||(res>=7*x));
}
if(res>=x*7)
{
Ans+=F(x/10,cnt2,cnt3,cnt5,cnt7+1,res-7*x,R||(res>=8*x));
}
if(res>=x*8)
{
Ans+=F(x/10,cnt2+3,cnt3,cnt5,cnt7,res-8*x,R||(res>=9*x));
}
if(res>=x*9)
{
Ans+=F(x/10,cnt2,cnt3+2,cnt5,cnt7,res-9*x,R||(res>=10*x));
}
Insert(t,tp,Ans);
return Ans;
}
////__attribute__((optimize("O2"))
int main()
{
ll L,R;
Pow3[0]=Pow2[0]=Pow5[0]=Pow7[0]=1;
for(ll i=1;i<=60;i++)
Pow2[i]=Pow2[i-1]*2,
Pow3[i]=Pow3[i-1]*3,
Pow5[i]=Pow5[i-1]*5,
Pow7[i]=Pow7[i-1]*7;
read(n);
read(L),read(R);
L--,R--;
ll b1=1,b2=1;
while(b2<=R)b2=(b2<<3)+(b2<<1);
while(b1<=L)b1=(b1<<3)+(b1<<1);
b1/=10;b2/=10;
ll ans1=L==0?0:F(b1,0,0,0,0,L,false);
b1/=10;
while(b1)
{
ans1+=F(b1,0,0,0,0,b1*10-1,false);
b1/=10;
}
ll ans2=F(b2,0,0,0,0,R,false);
b2/=10;
while(b2)
{
ans2+=F(b2,0,0,0,0,b2*10-1,false);
b2/=10;
}
printf("%lld\n",ans2-ans1);
// printf("%d %d",f,k);
return 0;
}