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

这道题,其实就是求包含大于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. 267C

    二分+高斯消元 我们利用物理里的势能来表示,每个点有一个势能h,再由流量守恒可以得到deg[x]*h[x]=sigma(h[y]) 如果x,y之间有边.这个式子是由流量守恒推出的,所以当x=1或n是不 ...

  2. .Net Core项目上Azure Docker云

    1.找到创建资源-容器-Container Instances 2.安装模板,填写私有映像表的相关信息 3.创建成功,运行测试.

  3. 【专题】概率期望DP

    11.22:保持更新状态:主要发一些相关的题目和个人理解 (P.S.如果觉得简单,可以直接看后面的题目) upd 11.30 更完了 [NO.1] UVA12230 Crossing Rivers  ...

  4. git的常用命令。。

    git的常用命令.. git help <command>  显示command的help git show  显示某次提交的内容 git show $id git co -- <f ...

  5. 【HTTP】如何正常关闭连接

    参考:<HTTP权威指南> 所有HTTP客户端.服务器或者代理都可以任意时刻关闭一条TCP传输连接.但是服务器永远无法确定它关闭“空闲”连接的那一刻,在线路那一头的客户端有没有数据要发送. ...

  6. matplotlib之pyplot 知识点滴

    以下是一些常用地址链接,请参考 matplotlib 官方网址 plt.plot()函数细节 Matplotlib 中文用户指南 4.6 编写数学表达式 Python seaborn matplotl ...

  7. 【原创】你知道Oracle 10G能存多少数据吗

    昨天晚上在看Oracle 10G联机文档中关于bigfile tablespaces的描述(引用1),发现了关于Oracle存储极限的简单描述.bigfile tablespaces的存在,让Orac ...

  8. Python3爬虫----爬取网页内的图片

    无聊把公司内网爬了一遍. https://github.com/gig886/Python/tree/master/爬虫

  9. POJ 3041 - 最大二分匹配

    这道题实现起来还是比较简单的,但是理解起来可能有点困难. 我最开始想到的是贪心法,每次消灭当前小行星最多的一行或一列.然而WA了.Discuss区里已经有高人给出反例. 下面给出正确的解法 我们把行和 ...

  10. SLAM: Ubuntu14.04_Kylin安装ROS-Indigo

    参考连接:ROS-Indigo版在Ubuntu上的安装第一步: 软件源配置 1. 增加下载源(增加ubuntu版的ros数据仓库,即下载源)(通用指令适合任何版本的ros) sudo sh -c 'e ...