poj3899 The Lucky Numbers 模拟+数学

题目链接: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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值