poj-3899-The Lucky Numbers 模拟+数学

2014-11-23 22:54:06 · 作者: · 浏览: 3
题目意思:
求给定区间内,只含4、7的数的个数以及通过反转后在该区间内的个数和。
解题思路:
模拟+数学。
代码解释的很详细,请看代码。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
using namespace std;

/*
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
*/
char A[50],B[50];
//g1(a,b,len) 表示1-a中后缀为b的lucky数,其中len是b的长度
//g2(a,b)表示1-a中反转后大于b的lucky数
//A-B 之间的lucky数个数为 g1(B,0,0)-g1(A-1,0,0)
//反转后在A-B 之间的lucky数为 g2(A,A)-g2(A,B)+g2(B,B)-g2(A,B)

ll g1(char * a,char * b,int len)
{
   int alen=strlen(a);
   ll res=0;
   bool ism=false;

   for(int i=0;i=
   {
      int j=i+alen-len;
      if(a[j]>b[i])
         break;
      else if(a[j]'7') //4和7都可以
      {
         res+=(ll)1<<(m-i);
         break;
      }
      else if(a[i]=='7') //4一定可以,7再往后计算
         res+=(ll)1<<(m-i-1);//把是4的情况计算清楚,后面就是7的情况
      else if(a[i]>'4'&&a[i]<'7')
      {
         res+=(ll)1<<(m-i-1); //放4的情况,后面可以任意
         break;
      }
      else if(a[i]<'4')
         break;
   }
   if((i==m)&&!ism) //计算临界情况
      res++;
   return res;
}

ll g2(char * a,char * b) //1-a之间,反转后大于b的lucky数
{  //b的长度肯定要>=a的长度
    int alen=strlen(a);
    char tmp[50],*last=&tmp[49];  //从后往前
    ll res=0;

    for(int i=0;i'7')  //高位已经超过7了,不可能超过它了
         break ;
       else if(b[i]=='7') //边界情况
            *(last--)='7';
       else if(b[i]>'4'&&b[i]<'7') //只要满足这
       {
          *last='7'; //只要把后面的这一位置成7,前面的可以任意了
          res+=g1(a,last,i+1);
          break;
       }
       else if(b[i]=='4')
       {
          *last='7';
          res+=g1(a,last,i+1); //把这位放7,前面的就任意了
          *(last--)='4'; //然后把它放4作为临界情况
       }
       else
       {
          *last='7'; //后面放7,前面就任意了
          res+=g1(a,last,i+1);
          *last='4'; //后面放4,前面就任意了
          res+=g1(a,last,i+1);
          break;
       }
    }
    //因为是算大于的情况,临界情况就不用考虑了
    return res;
}

int main()
{
   int  t;

   char aa[4]="999",bb[2]="7";
   printf("%I64d\n",g1(aa,bb,1));

   scanf("%d",&t);
   while(t--)
   {
      scanf("%s%s",A,B);
      int lea=strlen(A),leb=strlen(B);

      if(A[lea-1]!='0')
         --A[lea-1]; //是零的话就无所谓了
      ll ans=0;
      ans+=(g1(B,NULL,0)-g1(A,NULL,0)+g2(A,A)+g2(B,B));
      if(lea==leb)
         ans-=(2*g2(A,B));
      printf("%I64d\n",ans);

   }
   return 0;
}