题目链接:http://poj.org/problem?id=3899
Description
John and Brus are freshmen at the primary school. Their first home task is to learn some integer numbers. It is not so hard for the guys and they decide to impress their teacher by learning all lucky numbers between A and B, inclusive.
As you already know from the previous year contest 4 and 7 are lucky digits, and all the other digits are not lucky. A lucky number is a number that contains only lucky digits in decimal notation.
After learning all lucky numbers in [A, B] range John and Brus still have some free time and now they decide to learn additionally each lucky number N that is out of [A, B] range, but the reversed number of N is in this range. Here reversed number of N is the number N written in decimal notation, but the order of digits is reversed. For example, the reversed number of 447 is 744 and reversed number of 774474444 is 444474477.
You are given integers A and B and your task is to find the total number of lucky numbers learned by John and Brus.
Input
The first line contains single integer T – the number of test cases. Each test case consists of a single line containing two integers A and B separated by a single space.
Output
For each test case print a single line containing the total number of lucky numbers learned by John and Brus.
Sample Input
2
1 100
44 47
Sample Output
6
3
Hint
Constraints:
1 ≤ T ≤ 74,
1 ≤ A ≤ B ≤ 100000000000000000000000000000000000000000000000 (1047).
题意:求给定区间内lucky number 的个数以及 通过反转后得到的lucky number 在[a,b]内的lucky number数目之和。
分析:先求出[a,b]内的lucky number 数目,然后再求通过反转得到的lucky number
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=105;
char a[N],b[N];
LL cal(char *s,char *ss,int len)//小于s且后缀为ss的lucky number数目
{
LL ans=0;
int lena=strlen(s);
bool flag=false;
for(int i=0;i<len;i++)
{
if(s[lena-len+i]>ss[i])
{
break;
}
else if(s[lena-len+i]<ss[i])
{
flag=true;
break;
}
}
if(len==0)
{
for(int i=1;i<lena;i++)//位数小于等于lena的
ans+=((LL)1<<i);
}
int m=lena-len;
int i;
for(i=0;i<m;i++)//计数位数等于lena的
{
if(s[i]>'7')
{
ans+=(LL)1<<(m-i);
break;
}
else if(s[i]=='7')
{
ans+=(LL)1<<(m-i-1);
}
else if(s[i]>'4' && s[i]<'7')
{
ans+=(LL)1<<(m-i-1);
break;
}
else if(s[i]<'4')
{
break;
}
}
if(i==m && !flag)
ans++;
return ans;
}
LL Reverse(char *a,char *b)//0-a翻转大于b的lucky number 数目
{
LL ans=0;
char tmp[50];
char last[50];
int lena=strlen(a);
for(int i=0;i<lena;i++)
{
if(b[i]>'7')
{
break;
}
else if(b[i]=='7')
{
tmp[i]='7';
}
else if(b[i]>'4' && b[i]<'7')
{
tmp[i]='7';
int k=0;
for(int j=i;j>=0;j--)
last[k++]=tmp[j];
last[k]='\0';
ans+=cal(a,last,i+1);
break;
}
else if(b[i]=='4')
{
tmp[i]='7';
int k=0;
for(int j=i;j>=0;j--)
last[k++]=tmp[j];
last[k]='\0';
ans+=cal(a,last,i+1);
tmp[i]='4';
}
else
{
tmp[i]='7';
int k=0;
for(int j=i;j>=0;j--)
last[k++]=tmp[j];
last[k]='\0';
ans+=cal(a,last,i+1);
last[0]='4';
ans+=cal(a,last,i+1);
break;
}
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s%s",a,b);
int lena=strlen(a);
if(a[lena-1]!='0')
a[lena-1]--;
LL res=0;
res+=cal(b,NULL,0)-cal(a,NULL,0);
res+=(Reverse(a,a)+Reverse(b,b));
int lenb=strlen(b);
if(lena==lenb)
res-=2*Reverse(a,b);
printf("%lld\n",res);
}
return 0;
}