整理一下思路,明天再写。。。

这道题,其实就是求包含大于10的斐波那切数字的第K(K是斐波那契数)个数。注意到斐波那契数的爆炸性增长,所以在范围 内的符合要求的F数并不多吧。比如求第K个F数,那么,前K个F数都是这样的数,组成它们的数字中有斐波那契数。这就是字符串匹配吧。把这些数转化成字符串匹配,也就是很经典的数位DP,求范围内含有这些数字的数有多少个。

但是,所要含的数有很多个,怎么样匹配呢?转化成字符串,构成AC自动机来做。但是,说实话,求含有数字的个数确实不好弄,没关系,把它转化成不含有就容易了。于是,就成了AC自动机+数位DP了。但是,我们要求的是第K个,那么,因为个数是单调增的,求出刚好第K个可以使用二分查找来办到。

使用AC自动机来做数位DP,首先要构建trie图,然后明白哪些状态是可转移或不可转移的,然后在trie图上进行DP就可以了。

dp[i][j],即是当前是前第i位数位,并处在自动机的j状态上。

#include <iostream>
#include <cstdio>
#define LL __int64
using namespace std; const LL inf=10000000000000ll;
const int root=;
LL f[],ans[]; int trie[][],bit[],fail[],que[],head,tail;
int tot;
int nxt[][];
LL dp[][];
bool tag[]; void insert(LL now){
int len=;
while(now){
bit[++len]=now%;
now/=;
}
int p=root,i=len;
while(i--){
if(trie[p][bit[i+]]==-){
trie[p][bit[i+]]=++tot;
}
p=trie[p][bit[i+]];
}
tag[p]=true;
} void build_ac(){
head=tail=;
que[tail++]=root;
while(head!=tail){
int tmp=que[head++];
int p=-;
for(int i=;i<;i++){
if(trie[tmp][i]!=-){
if(tmp==root) fail[trie[tmp][i]]=root;
else{
p=fail[tmp];
while(p!=-){
if(trie[p][i]!=-){
fail[trie[tmp][i]]=trie[p][i];
break;
}
p=fail[p];
}
if(p==-) fail[trie[tmp][i]]=root;
}
if(tag[fail[trie[tmp][i]]]) tag[trie[tmp][i]]=tag[fail[trie[tmp][i]]];
que[tail++]=trie[tmp][i];
}
else{
if(tmp==root) trie[tmp][i]=root;
else{
p=fail[tmp];
while(p!=-){
if(trie[p][i]!=-){
trie[tmp][i]=trie[p][i];
break;
}
p=fail[p];
}
if(p==-) trie[tmp][i]=root;
}
}
}
}
} LL dfs(int len,int j,bool flag){
if(len==) return 1ll;
if(!flag&&dp[len][j]!=-) return dp[len][j];
LL ans=;
int up=flag?bit[len]:;
for(int i=;i<=up;i++){
if(tag[nxt[j][i]]||nxt[j][i]==-) continue;
ans+=dfs(len-,nxt[j][i],i==up&&flag);
}
if(!flag) dp[len][j]=ans;
return ans;
} LL cal(LL m){
LL tm=m+1ll;
int len=;
while(m){
bit[++len]=m%;
m/=;
}
return tm-dfs(len,,true);
// return 0;
} LL bin(LL num){
// cout<<cal(13)<<endl;
// system("pause");
LL l=,r=inf,ret=-,tmp;
while(l<=r){
LL m=(l+r)>>;
if((tmp=cal(m))>=num){
r=m-;
ret=m;
// cout<<m<<endl;
}
else l=m+;
}
return ret;
} int cal_next(int p,int j){
if(tag[p]) return -;
if(tag[trie[p][j]]) return -;
return trie[p][j];
} void Init(){
tot=;
memset(trie,-,sizeof(trie));
memset(tag,false,sizeof(tag));
memset(fail,-,sizeof(fail));
f[]=1ll; f[]=1ll;
for(int i=;i<=;i++){
f[i]=f[i-]+f[i-];
if(f[i]>){
insert(f[i]);
}
}
build_ac();
for(int i=;i<=tot;i++){
for(int j=;j<;j++)
nxt[i][j]=cal_next(i,j);
}
memset(dp,-,sizeof(dp));
int c=;
for(int i=;i<=;i++){
ans[c]=bin(f[i]);
// system("pause");
if(ans[c]==-) break;
c++;
// printf("%I64d %d\n",ans[c-1],c);
}
} int main(){
Init();
LL n;
// cout<<"YES"<<endl;
while(scanf("%I64d",&n)!=EOF&&n!=-){
LL ret=inf;
for(int i=;i<;i++){
LL tmp=n-ans[i];
// cout<<tmp<<endl;
if(tmp<) tmp=-tmp;
if(ret>tmp) ret=tmp;
}
printf("%I64d\n",ret);
}
return ;
}

HDU 4518的更多相关文章

  1. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  2. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  3. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

  4. HDU 4569 Special equations(取模)

    Special equations Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  5. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  6. HDU 1796How many integers can you find(容斥原理)

    How many integers can you find Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d ...

  7. hdu 4481 Time travel(高斯求期望)(转)

    (转)http://blog.csdn.net/u013081425/article/details/39240021 http://acm.hdu.edu.cn/showproblem.php?pi ...

  8. HDU 3791二叉搜索树解题(解题报告)

    1.题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=3791 2.参考解题 http://blog.csdn.net/u013447865/articl ...

  9. hdu 4329

    problem:http://acm.hdu.edu.cn/showproblem.php?pid=4329 题意:模拟  a.     p(r)=   R'/i   rel(r)=(1||0)  R ...

随机推荐

  1. OC常用的数学函数及宏定义

    一.函数 1. 三角函数 double sin (double);正弦 double cos (double);余弦 double tan (double);正切 2 .反三角函数 double as ...

  2. google搜索引擎使用方法

    搜索引擎命令大全!这是一个我最喜欢的Google搜索技巧的清单: link:URL = 列出到链接到目标URL的网页清单. related:URL = 列出于目标URL地址有关的网页. site:ht ...

  3. bzoj1705[Usaco2007 Nov]Telephone Wire 架设电话线(dp优化)

    1705: [Usaco2007 Nov]Telephone Wire 架设电话线 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 441  Solved: ...

  4. C#三种创建对象方法所需时间比较。。。。。

    C#创建对象的三种方法  new().Activator.Assembly,接下来通过代码直接来看看运行的速度.... 首先,先看看三种创建对象实例的方法: //new(); public stati ...

  5. Redis hash结构 和常用命令

    Redis 数据结构 -- 哈希 hash 是 一个 String 类型的field 和 value 的映射表 hash 的键值 对在内存中的一种无序的状态 命令 说明 备注 hdel key fie ...

  6. 5.23@Comfiguration的解释

    @Configuration:代表这个类是一个配置类. @ComponentScan:用来扫描指定包下面的注解类. @Import:用来导入其他的@Configuration配置类. @ImportR ...

  7. 浅谈Websocket、Ajax轮询和长轮询(long polling)

    浅谈Websocket.Ajax轮询和长轮询(long p0ll) 最近看到了一些介绍Websocket的文章,觉得挺有用,所以在这里将自己的对其三者的理解记录一下. 1.什么是Websocket W ...

  8. HIVE 命令记录

    HIVE 命令记录 设置hive运行的队列 hive> set mapreduce.job.queuename=ven12; 打印列名 hive> set hive.cli.print.h ...

  9. 2013款MacBook Air装Windows7单系统

    经过两天的摸索,查找无数资料终于把2013款的MacBook Air装上了WIN 7,虽然网上有很多的资料但是都不是我想要的,第一个我的是2013款的MacBook Air,跟原来2012 11款Ma ...

  10. 2星|《工业X.0》:物联网的资料汇编

    工业X.0:实现工业领域数字价值 看完比较失望,没有看到新的观点想法.基本算是物联网的资料汇编.总体评价2星. 以下是书中一些内容的摘抄: 1:例如,埃森哲为其员工开发了一个用例,用增强现实技术解决实 ...