HDU 4518
整理一下思路,明天再写。。。
这道题,其实就是求包含大于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的更多相关文章
- HDOJ 2111. Saving HDU 贪心 结构体排序
Saving HDU Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 【HDU 3037】Saving Beans Lucas定理模板
http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...
- hdu 4859 海岸线 Bestcoder Round 1
http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...
- HDU 4569 Special equations(取模)
Special equations Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u S ...
- HDU 4006The kth great number(K大数 +小顶堆)
The kth great number Time Limit:1000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64 ...
- HDU 1796How many integers can you find(容斥原理)
How many integers can you find Time Limit:5000MS Memory Limit:32768KB 64bit IO Format:%I64d ...
- hdu 4481 Time travel(高斯求期望)(转)
(转)http://blog.csdn.net/u013081425/article/details/39240021 http://acm.hdu.edu.cn/showproblem.php?pi ...
- HDU 3791二叉搜索树解题(解题报告)
1.题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=3791 2.参考解题 http://blog.csdn.net/u013447865/articl ...
- hdu 4329
problem:http://acm.hdu.edu.cn/showproblem.php?pid=4329 题意:模拟 a. p(r)= R'/i rel(r)=(1||0) R ...
随机推荐
- MVC + Redis
net MVC + Redis(hash入库+log4net集成) https://www.cnblogs.com/hoyu/p/9063675.html 博客四元素 既然要写一个博客类的网站,那就应 ...
- 莫队&&分块
今天兔哥讲了一波莫队,比较有趣,先加一个链接,这是她的教程 rabbithu.cnblogs.com 这里就不详细说了,其实就是两个指针来优化的暴力.一开始排序函数有问题,没用上莫队的核心思想:把查询 ...
- 在linux服务器centos上使用svn同步代码到项目中
一.需求 1.在多人开发过程中代码的管理以及版本的控制是一个很重要的问题,因为在开发过程中我们可能会同时更改过某个文件或者更改过多个文件, 这会导致我们很容易发生错误.所以我们需要一个方式去管理我们的 ...
- B - Bit++
Problem description The classic programming language of Bitland is Bit++. This language is so peculi ...
- spring 九种设计模式
spring中常用的设计模式达到九种,我们举例说明: 第一种:简单工厂 又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一. 简单工厂模式的实质是由一 ...
- Java 基本的递归写法
1.首先我们得有一个树状结构的表,类似这种结构.必须得有 id,pid 其他的根据需要来. 我们叫它treeTbl表吧.这里pid为0的表示是顶级节点. 2.接着select * from tree ...
- 网站html代码解析
1.什么是HTML文件?HTML中文叫做“超文本标记语言”,一个HTML文件不仅包含文本内容,还包含一些标记,一个HTML文件的后缀名是.htm或者是.html.用文本编辑器(Dreamweaver) ...
- VMware中linux安装jdk
首先安装linux系统 如何将jdk安装包复制到linux中不做概述,可以使用xftp工具,或者Xshell,或者其他方式. 1.下载jdk包:本章使用的为后缀为tar.gz的文件(不需要安装),如j ...
- Android Studio项目中有用文件与可忽略文件(初学者)
可通过Settings --> Version Control --> Ignored Files进行设置或察看: 支持指定文件或文件夹,也支持匹配模式. Android Studio 中 ...
- 复习java基础第四天(集合:List、Map、Collections、Enumeration)
一.List: List 代表一个元素有序.且可重复的集合,集合中的每个元素都有其对应的顺序索引 List 允许使用重复元素,可以通过索引来访问指定位置的集合元素. List 默认按元素的添加顺序设置 ...