题目链接:

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\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;
}

poj-3899-The Lucky Numbers 模拟+数学的更多相关文章

  1. HDU 5676 ztr loves lucky numbers (模拟)

    ztr loves lucky numbers 题目链接: http://acm.hust.edu.cn/vjudge/contest/121332#problem/I Description ztr ...

  2. codeforces 630C Lucky Numbers

    C. Lucky Numbers time limit per test 0.5 seconds memory limit per test 64 megabytes input standard i ...

  3. hdu 5676 ztr loves lucky numbers(dfs+离线)

    Problem Description ztr loves lucky numbers. Everybody knows that positive integers are lucky if the ...

  4. codeforces 630C - Lucky Numbers 递推思路

    630C - Lucky Numbers 题目大意: 给定数字位数,且这个数字只能由7和8组成,问有多少种组合的可能性 思路: 假设为1位,只有7和8:两位的时候,除了77,78,87,88之外还哇哦 ...

  5. hdu 5676 ztr loves lucky numbers 打表+二分

    ztr loves lucky numbers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/ ...

  6. ZCMU 2177 Lucky Numbers (easy)

    传送门: http://acm.zcmu.edu.cn/JudgeOnline/problem.php?id=2177 2177: Lucky Numbers (easy) 时间限制: 2 Sec   ...

  7. hdu-5676 ztr loves lucky numbers(乱搞题)

    题目链接: ztr loves lucky numbers  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 65536/65536 K ( ...

  8. C - Lucky Numbers (easy)

    Problem description Petya loves lucky numbers. Everybody knows that positive integers are lucky if t ...

  9. Codeforces Round #160 (Div. 2)---A. Roma and Lucky Numbers

    Roma and Lucky Numbers time limit per test 1 second memory limit per test 256 megabytes input standa ...

随机推荐

  1. 算法导论 6-2 d叉堆

    问题: d叉堆性质与二叉堆相似,但其每个非叶子结点有d个孩子: 1) 如何在一个数组中表示一个d叉堆? 2) 包含n个元素的d叉堆的高度是多少? 3) 给出 EXTRACT-MAX在d叉堆的有效实现, ...

  2. Cocos2d-x C++调用Android弹出提示框

    转载请注明地址,谢谢.. Cocos2d-x中提供了一个JniHelper类来让我们对Jni进行操作. (PS:弄了一天想自己写代码操作Jni的,但是总是出错,技术差不得不使用Cocos2d-x现成的 ...

  3. IOS开发之格式化日期时间的使用 && 编程中常见问题

    今天在做一个有关时间的一些开发的时候,遇见了一写问题,反正来说既是很简单的问题,但毕竟用了我一些时间去调错误,遂记录之. 本来是想用 NSDateFormat 来转换一下服务器返回的时间,然后在客户端 ...

  4. js获取浏览器地址栏传递的参数

    function getQueryString(key){ var href=window.location.href; var reg = new RegExp(key +"=([^&am ...

  5. 建立dblink,clob

    建立dblink的方法, 如果有个测试库A,要访问生产库里的数据,那么可以直接在测试库A里建立一个dblink,然后数据库A就可以直接访问测试库B的数据了. -- 删除已有的dblink drop d ...

  6. 深入浅出—JAVA(5)

    5.编写程序

  7. Mono for Android 显示远程图片

    Main.axml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:an ...

  8. QT5下获取本机IP地址、计算机名、网络连接名、MAC地址、子网掩码、广播地址

    获取主机名称 /* * 名称:get_localmachine_name * 功能:获取本机机器名称 * 参数:no * 返回:QString */ QString CafesClient::get_ ...

  9. 转:C++中引用传递与指针传递区别

    从概念上讲.指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变. 而引用是一个别名,它在逻辑上不是独立的,它的存在具有 ...

  10. linux shell 执行多个命令的方法

    (1)在每个命令之间用:(分号)隔开. (2)在每个命令之间用&&隔开. &&表示:若前一个命令执行成功,才会执行下一个.这样,可确保所有的命令执行完毕后,其执行过程都 ...