#include<bits/stdc++.h>
using namespace std;
/*
题意:求给出的A和B之间没有4和连续的37的数字的个数
1<=A<=B<=2000000000
*/
int f[11][11]={0};
int solve(int x)//从小到大考虑
{
int a[11]={0};//分解x
while(x)a[++a[0]]=x%10,x/=10;
int ret=0;
for(int i=1;i<a[0];i++)//枚举位数,不足a[0]位
for(int j=1;j<=9;j++)ret+=f[i][j];//枚举最高位数字为j
for(int i=1;i<a[a[0]];i++)ret+=f[a[0]][i];//最高位不足a[a[0]]
if(a[a[0]]==4)return ret;
for(int i=a[0]-1;i>=1;i--)//从次高位往下
{
//枚举第i位数字为j,依题意和第i+1位比较
for(int j=0;j<a[i]+(i==1);j++)if(j!=4&&!(a[i+1]==3&&j==7))ret+=f[i][j];
//最大的数字已出现不合法情况则直接返回
if(a[i]==4||(a[i+1]==3&&a[i]==7))return ret;
}
return ret;
}
int main()
{
//f[i][j]表示i位数字,首位数字为j的情况总数
for(int i=0;i<=9;i++)if(i!=4)f[1][i]=1;//初始化1位的情况
for(int i=2;i<=10;i++)//枚举位数
for(int j=0;j<=9;j++)//枚举首位//注意在初始化f的过程中前导0是允许的
for(int k=0;k<=9;k++)//枚举次位
{
if(j!=4&&k!=4&&!(j==3&&k==7))f[i][j]+=f[i-1][k];
}
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",solve(y)-solve(x-1));//注意边界值x也要考虑
return 0;
}
#include<bits/stdc++.h>
using namespace std;
/*
题意:求区间[X,Y]内恰好等于K个互不相等的B的整数次幂之和的数的个数
数据范围:1<=X<=Y<=2^31-1 1<=K<=20 2<=B<=10
思路:
把询问的数转换成B进制xb,则要求的数为每个B进制数位上有K个1且小于xb的数
设f(i,j,k)表示第i位,首位为j,已经用了k个1的数的个数
*/
int X,Y,K,B,a[35]={0},f[35][2][25]={0};
int cal(int x)
{
int ret=0;a[0]=0;
while(x)a[++a[0]]=x%B,x/=B;//把询问的数转换成B进制
for(int i=1;i<=a[0]-1;i++)ret+=f[i][1][K];//枚举位数小于a的数
if(a[a[0]]>1)return ret+f[a[0]][1][K];//最高位已经大于1了,就直接返回了
int sum=1;//从高位推到低位时,已经用了的1的个数
for(int i=a[0]-1;i>=1;i--)
{
if(a[i]==1)
{
ret+=f[i][0][K-sum];//当前位为1则可以加上小于当前位的所有情况
sum++;//把当前位为1的情况加上
}
//超过1则包含所有情况
else if(a[i])return ret+f[i][0][K-sum]+f[i][1][K-sum];
if(i==1)ret+=f[i][0][K-sum];//???
}
return ret;
}
int main()
{
scanf("%d%d%d%d",&X,&Y,&K,&B);
//初始化
f[1][0][0]=1;//1位,首位为0、用了0个1的数有一个
f[1][1][1]=1;//1位,首位为1、用了1个1的数有一个
for(int i=2;i<=30;i++)//枚举B进制数,每个数位全为1或0的数的位数
for(int j=0;j<=1;j++)//枚举首位为0或1
for(int k=0;k<=K;k++)//枚举已经用了的1的个数
for(int t=0;t<=1;t++)//枚举上一个状态已经用了的1的个数
if(k-j>=0)f[i][j][k]+=f[i-1][t][k-j];
cout<<cal(Y)-cal(X-1)<<endl;
return 0;
}