zoukankan      html  css  js  c++  java
  • poj-3899-The Lucky Numbers 模拟+数学

    题目链接:

    http://poj.org/problem?id=3899

    题目意思:

    求给定区间内,只含4、7的数的个数以及通过反转后在该区间内的个数和。

    解题思路:

    模拟+数学。

    代码解释的很详细,请看代码。

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<stack>
    #include<list>
    #include<queue>
    #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<len;i++) //比较a的后len位与b的大小,>=
       {
          int j=i+alen-len;
          if(a[j]>b[i])
             break;
          else if(a[j]<b[i])
          {
             ism=true;
             break;
          }
       }
       if(len==0)  //先算出低于alen位的总的lucky数
       {
          for(int i=1;i<alen;i++)
             res+=(ll)1<<i;  //i位的话一共有2^i个lucky数
       }//如果len!=0 那么前面的m位中也有1-m,这种情况好像没考虑啊
       int m=alen-len; //计算与a位数相同lucky数
       int i;
       for(i=0;i<m;i++) //一位一位从前往后考虑
       {
          if(a[i]>'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<alen;i++)
        {
           if(b[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
    ",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
    ",ans);
    
       }
       return 0;
    }
    
    
    
    
    


  • 相关阅读:
    关于UI设计的文章汇总
    Linq 中不爽之处
    难题autoconf、automake、libtool
    静态构造函数线程安全的几个版本[转载]
    Window Live Writer
    Guid、Int、BigInt编号的速度和存储空间的比较
    MVP模式中的P和V关系
    LR 剖析器
    快速软件开发 学习笔记 之七
    快速软件开发 学习笔记 之六
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3201158.html
Copyright © 2011-2022 走看看