题意:如果一个数中的某一段是长度大于2的菲波那契数,那么这个数就被定义为F数,前几个F数是13,21,34,55......将这些数字进行编号,a1 = 13, a2 = 21。现给定一个数n,输出和n相差最小的数ax与n的差值的绝对值,其中下标x满足是一个菲波那契数。

分析:该题所求真是九曲十八弯,说了那么多其实要解决的问题可以转化为给定一个x,求1-x之间有多少个F数,通过二分查找能够把下标是菲波那契数的序列求出来,之后就直接for循环找到那个最相近的数就可以了。关键是如何求解1-x之间有多少个F数,容易想到的是数位dp,但是这里不太好弄,因为10^11次方之内有50多个数,每个数又有一定的长度,因此通过枚举每一数位来直接dp状态记录成了问题,而ac自动机能够解决多串匹配的问题,因此通过建立一个ac自动机(使用静态数组实现),把状态映射到ac自动机上的静态数组下标上,这样一来状态数少了不说而且能够把这个匹配过程表示出来。其他地方和一般的数位dp没什么区别了。C++编译器调用abs函数WA了,看了看头文件确实没有long long型的重载,不过G++中调用abs竟然过了,因此索性改成手动判负。最近dev也不知怎么搞的,%I64d无法读入long long啊,本地不过提交AC这种事情真忧伤,索性cin了。

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std; typedef long long LL;
const int N = ;
LL n;
int bit[];
LL f[];
LL dp[][N]; // dp[i][j]表示剩余i位没有限制,并且已经在自动机中匹配到j位置的F数的个数
LL POW[]; // 存储10的幂
LL seq[];
LL suf[];
queue<int>q; struct Ac_Auto{
int ch[N][];
int fail[N];
bool flag[N];
int idx, root;
int newnd() {
memset(ch[idx], , sizeof (ch[idx]));
flag[idx] = false, fail[idx] = ;
return idx++;
}
void init() {
idx = , root = newnd();
}
void insert(LL x) {
int id = ;
while (x) bit[id++] = x%, x/=;
int p = root;
for (int i = id-; i >= ; --i) {
if (!ch[p][bit[i]]) ch[p][bit[i]] = newnd();
p = ch[p][bit[i]];
}
flag[p] = true;
}
void build() {
for (int i = ; i < ; ++i) {
if (ch[root][i]) {
q.push(ch[root][i]);
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = ; i < ; ++i) {
int &v = ch[u][i];
int x = fail[u];
if (v) {
q.push(v);
while (x && !ch[x][i]) x = fail[x];
fail[v] = ch[x][i];
flag[v] = flag[v] || flag[fail[v]];
} else {
v = ch[x][i]; // 直接通过引用来更改,叼啊
}
}
}
}
void find(LL x) {
int id = ;
while (x) bit[id++] = x%, x/=;
int p = root;
for (int i = id-; i >= ; --i) {
p = ch[p][bit[i]];
if (flag[p]) {
cout << "OMG" << endl;
return;
}
}
}
};
Ac_Auto ac; LL count(int p, int sta, bool bound) {
if (p == ) return ;
if (!bound && ~dp[p][sta]) return dp[p][sta];
int y = bound ? bit[p] : ;
LL sum = ;
int tsta;
for (int i = ; i <= y; ++i) {
tsta = ac.ch[sta][i];
if (ac.flag[tsta]) {
if (bound&&i==y) sum += suf[p-]+;
else sum += POW[p-];
continue;
}
sum += ::count(p-, tsta, bound&&i==y);
}
if (!bound) dp[p][sta] = sum;
return sum;
} LL cal(LL x) {
int idx = ;
while (x) suf[idx] = suf[idx-]+x%*POW[idx-], bit[idx++] = x%, x/=;
return ::count(idx-, ac.root, true);
} void prepare() {
f[] = , f[] = ;
for (int i = ; i <= ; ++i) {
f[i] = f[i-] + f[i-];
}
ac.init();
for (int i = ; i <= ; ++i) {
ac.insert(f[i]);
}
ac.build();
POW[] = ;
for (int i = ; i < ; ++i) POW[i] = POW[i-] * ;
memset(dp, 0xff, sizeof (dp));
LL tmp;
for (int i = ; i <= ; ++i) {
LL l = , r = POW[], mid;
while (l <= r) {
mid = (l + r) >> ;
if ((tmp=cal(mid)) < f[i]) l = mid + ;
else if (tmp > f[i]) r = mid - ;
else seq[i] = mid, r = mid - ;
}
}
} int main() {
prepare();
while (cin >> n, n != -) {
LL ret = 1LL << ;
for (int i = ; i <= ; ++i) {
LL t = seq[i] - n;
if (t < ) t = -t;
ret = min(ret, t);
}
cout << ret << endl;
}
return ;
}

HDU-4518 吉哥系列故事——最终数 AC自动机+数位DP的更多相关文章

  1. 吉哥系列故事——恨7不成妻(数位DP)

    吉哥系列故事——恨7不成妻 http://acm.hdu.edu.cn/showproblem.php?pid=4507 Time Limit: 1000/500 MS (Java/Others)   ...

  2. hdu4507吉哥系列故事——恨7不成妻 (数位dp)

    Problem Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: ...

  3. hdu-4507 吉哥系列故事——恨7不成妻 数位DP 状态转移分析/极限取模

    http://acm.hdu.edu.cn/showproblem.php?pid=4507 求[L,R]中不满足任意条件的数的平方和mod 1e9+7. 条件: 1.整数中某一位是7:2.整数的每一 ...

  4. HDU-4507 吉哥系列故事——恨7不成妻 数位DP

    题意:给定区间[L, R]求区间内与7无关数的平方和.一个数当满足三个规则之一则认为与7有关:1.整数中某一位是7:2.整数的每一位加起来的和是7的整数倍:3.这个整数是7的整数倍: 分析:初看起来确 ...

  5. 【hdu4507】吉哥系列故事——恨7不成妻 数位dp

    题目描述 求 $[L,R]$ 内满足:数位中不包含7.数位之和不是7的倍数.本身不是7的倍数 的所有数的平方和 mod $10^9+7$ . 输入 输入数据的第一行是case数T(1 <= T ...

  6. hdu4507 吉哥系列故事——恨7不成妻[数位DP]

    这题面什么垃圾玩意儿 首先看到问题格式想到数位DP,但是求的是平方和.尝试用数位DP推出. 先尝试拼出和.设$f[len][sum][mod]$表示填到$len$位,已填位置数位和$sum$,数字取余 ...

  7. hdu 4512 吉哥系列故事——完美队形I【LCIS经典应用】

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=4512 http://acm.hust.edu.cn/vjudge/contest/view.action ...

  8. HDU 4513 吉哥系列故事――完美队形II(Manacher)

    题目链接:cid=70325#problem/V">[kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher V - 吉哥系列故事――完美队形I ...

  9. HDU 4513 吉哥系列故事――完美队形II

    http://acm.hdu.edu.cn/showproblem.php?pid=4513 吉哥系列故事——完美队形II Time Limit: 3000/1000 MS (Java/Others) ...

随机推荐

  1. Length of Last Word

    class Solution { public: int lengthOfLastWord(string s) { ; ; while(s[i]&&s[i]==' ') i++; // ...

  2. rsync 只同步指定类型的文件

    需求: 同步某个目录下所有的图片(*.jpg),该目录下有很多其他的文件,但只想同步*.jpg的文件. rsync 有一个--exclude 可以排除指定文件,还有个--include选项的作用正好和 ...

  3. [PHP100] PHP如何防止注入及开发安全

    1.PHP注入的基本原理 程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对 用户输入数据的合法性进行判断,使应用程序存在安全隐患.用户可以提交一段数据 库查询代码,根据程序返回 ...

  4. 7、XML加强/Web开发/Tomcat

    1 XML加强 XML加强 1)Dom4j修改XML文档 写出xml文档: XMLWriter writer = new XMLWriter() writer.wrtite(doc); 增加: Doc ...

  5. ACM题目————滑雪

    Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道 ...

  6. 64位系统安装ODBC驱动的方法

    为了更充分的利用硬件资源,我想很多人都开使用64位操作系统了,同时你可以也发现了在64位操作系统上ODBC的驱动找不到了,所以ODBC的东西都没法用了. 因为2007以前版本的Office只有32位版 ...

  7. xcode4.3 完成输入后 点击背景关闭键盘

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [self.view endEditing:YES];} 把这个复制到 ...

  8. {A} + {B} 分类: HDU 2015-07-11 18:06 6人阅读 评论(0) 收藏

    {A} + {B} Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  9. java中|与||,&与&&到底有什么区别呢?

    &是位运算符.&&是布尔逻辑运算符.在运行上,&两边的条件都要判断(不管前面的是ture还是false),而&&先判断前面的,若为false,则后面的不 ...

  10. #ifdef _DEBUG

    #ifdef _DEBUG virtual void AssertValid() const; //assert(断言)valid(有效的,正确的) virtual void Dump(CDumpCo ...