http://acdream.info/problem?pid=1064
求L到r之间含有3不含有8 或者 含有8不含有3的数的数量。
大思路就是用1-r符合条件的数减去1-(L-1)符合条件的数。
至于求有多少个,就是数位dp的知识了,从高位开始向后去数。
可以先将前10,100,1000,10000,100000等中包含一个数不包含另一个数的情况打表算出来。
算的时候要注意算到后面的位数的时候要标记前面高位有无出现3或者8.
#include<bits/stdc++.h>
using namespace std;
long long int ans1[22]={0,1,17,217,2465,26281,269297,2685817,26269505,253202761};
long long int ans2[22]={0,9,81,81*9,81*81,81*81*9,81*81*81,81*81*81*9,81*81*81*81,81*81*81*81*9};
long long int find(char a[])
{
int l=strlen(a);
long long int ans=0; bool f1=0,f2=0;
int i;
for(i=0;i<=l-2;i++)
{
if(f1==0&&f2==0)
{
if(a[i]<='3')
{
ans+=ans1[l-i-1]*2*(a[i]-'0');
}
else if(a[i]>'3'&&a[i]<='8')
{
ans+=ans1[l-i-1]*(2*(a[i]-'0'-1))+ans2[l-i-1];
}
else ans+=ans1[l-i-1]*(2*(a[i]-'0'-2))+ans2[l-i-1]*2;
}
if(f1==1&&f2==0)
{
if(a[i]<='8')
{
ans+=ans2[l-i-1]*(a[i]-'0');
}
else ans+=ans2[l-i-1]*((a[i]-'0')-1);
}
if(f1==0&&f2==1)
{
if(a[i]<='3')
{
ans+=ans2[l-i-1]*(a[i]-'0');
}
else ans+=ans2[l-i-1]*((a[i]-'0')-1);
}
if(a[i]=='3')f1=1;
if(a[i]=='8')f2=1;
}
if(f1==0&&f2==0)
{
if(a[l-1]<'3');
else if(a[l-1]>='8')ans+=2;
else ans+=1;
}
if(f1==1&&f2==0)
{
if(a[l-1]>='8')
ans+=a[l-1]-'0';
else ans+=a[l-1]-'0'+1;
}
if(f1==0&&f2==1)
{
if(a[l-1]>='3')
ans+=a[l-1]-'0';
else ans+=a[l-1]-'0'+1;
}
return ans;
}
int main(){
char a[111],b[111];
int n;
cin>>n;
while(n--)
{
cin>>a>>b;
long long int ans=find(a);
long long int ans12=find(b);
bool f1=0,f2=0;
for(int i=0;i<strlen(a);i++)
{
if(a[i]=='3')f1=1;
if(a[i]=='8')f2=1;
}
if(f1!=f2)
ans--;
//cout<<ans<<" "<<ans12<<endl;
cout<<ans12-ans<<endl;
}
return 0;
}