HDU 4518 解题报告
来源:互联网 发布:淘宝象印官方旗舰店 编辑:程序博客网 时间:2024/04/19 21:47
1到1e11的斐波那契数很少,显然可以预处理出来。
然后枚举这些数,假设其为k,那么可以利用二分数位dp去查找第k个F数,calc(x)就是要求出1-x有多少个F数。
这里的问题是,怎么表示状态。
因为斐波那契数是字符串,而且数位dp是一个字符一个字符加上去的,无论是用map映射,还是hash数组,都不好转移,我们利用ac自动机里面,每个单词的结尾部分的节点值就表示这个单词,那么状态就完美解决了,惊奇的是,在数位dp做转移的时候也方便许多。
然后状态就是:dp[i][j][]。前i位,当前走到j节点,是否已经包含斐波那契数。
/*纳兰性德 -清《长相思·山一程》山一程,水一程,身向榆关那畔行,夜深千帐灯。风一更,雪一更,聒碎乡心梦不成,故园无此声。*/// Created by Matrix on 2016-02-02// Copyright (c) 2015 Matrix. All rights reserved.//////#pragma comment(linker, "/STACK:102400000,102400000")#include <algorithm>#include <cctype>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <map>#include <queue>#include <string>#include <sstream>#include <set>#include <vector>#include <stack>#define ALL(x) x.begin(), x.end()#define INS(x) inserter(x, x,begin())#define ll long long#define CLR(x) memset(x, 0, sizeof x)using namespace std;const ll inf = 0x3f3f3f3f3f3f3f3f;const int MOD = 1e9 + 7;const int maxn = 1e6 + 10;const int maxv = 1e3 + 10;const double eps = 1e-9;const int Size = 10;int nxt[maxv][10];int have[maxv], fail[maxv];struct AcAmount { int cnt; int root; int newNode() { for(int i = 0; i < Size; i++) { nxt[cnt][i] = -1; } have[cnt++] = 0; return cnt - 1; } void init() { cnt = 0; root = newNode(); } void insert(ll k) { int digit[20]; int len = 0; int now = root; while(k) { digit[len++] = k % 10; k /= 10; } for(int i = len - 1; i >= 0; i--) { int num = digit[i]; if(nxt[now][num] == -1) nxt[now][num] = newNode(); now = nxt[now][num]; } have[now] = 1; } void build() { fail[root] = root; queue <int> que; for(int i = 0; i < Size; i++) { if(nxt[root][i] == -1) { nxt[root][i] = root; } else { fail[nxt[root][i]] = root; que.push(nxt[root][i]); } } while(que.size()) { int u = que.front(); que.pop(); for(int i = 0; i < Size; i++) { int &v = nxt[u][i]; if(v == -1) { v = nxt[fail[u]][i]; } else { fail[v] = nxt[fail[u]][i]; have[v] |= have[fail[v]]; que.push(v); } } } }};ll fab[100];int tot;ll dp[20][maxv][2];ll digit[20];void Init() { AcAmount ac; ac.init(); tot = 2; fab[1] = 1; fab[2] = 1; for(int i = 3; i < 100; i++) { if(fab[i-1] + fab[i-2] > (ll)2e11) break; fab[++tot] = fab[i-1] + fab[i-2];// cout << fab[i] << endl; }// cout << tot <<endl; for(int i = 1; i <= tot; i++) { if(fab[i] < 10) continue; ac.insert(fab[i]); } ac.build(); memset(dp, -1, sizeof dp);}ll dfs(int step, int pos, int flag, int limit) { if(!step) return flag > 0; if(!limit && dp[step][pos][flag] != -1) return dp[step][pos][flag]; ll ret = 0; int up = limit ? digit[step] : 9; for(int i = 0; i <= up; i++) { int j = nxt[pos][i]; ret += dfs(step-1, j, have[j] | flag, limit && i == up); } if(!limit) dp[step][pos][flag] = ret; return ret;}ll Calc(ll n) { int cnt = 0;// memset(dp, -1, sizeof dp); while(n) { digit[++cnt] = n % 10; n /= 10; }// cout << tm << "********" << dfs(cnt, 0, 1) << endl; return dfs(cnt, 0, 0, 1);}ll Find(ll n) { ll l = 1, r = (ll)4e12; while(l <= r) { ll mid = (l + r) / 2; ll num = Calc(mid);// printf("mid = %lld ", mid);// printf("num = %lld\n", num); if(num >= n) r = mid - 1; else l = mid + 1;// printf("l = %lld r = %lld\n", l, r); }// printf("n = %lld r = %lld\n", n, r); return r + 1;}int main() {#ifdef LOCAL freopen("in.txt", "r", stdin);// freopen("out.txt","w",stdout);#endif Init(); ll n;// for(int i = 12; i <= 40; i++) {// printf("i = %d calc = %lld\n", i, Calc(i));// } while(scanf("%I64d", &n) != EOF && n != -1) { ll ans = inf; for(int i = 2; i <= tot; i++) { ans = min(ans, abs(n - Find(fab[i]))); } printf("%I64d\n", ans);// for(int i = 1; i <= 3; i++) {// printf("%d %I64d\n", i, Find(i));// }// for(int i = 12; i <= 40; i++) {// printf("i = %d calc = %lld\n", i, Calc(i));// } } return 0;}
0 0
- HDU 4518 解题报告
- HDU 3342 解题报告
- HDU 3336 解题报告
- HDU 3335 解题报告
- hdu 2516解题报告
- hdu 1004解题报告
- hdu 2139解题报告
- hdu 1019解题报告
- hdu 1064 解题报告
- HDU 1113 解题报告
- hdu 1068 解题报告
- HDU:2050解题报告
- hdu 4001解题报告
- hdu 1005解题报告
- HDU解题报告--1003
- HDU解题报告--1004
- HDU解题报告--1005
- HDU 1005 解题报告
- 关于在头文件中定义变量
- 【Android开发小记--5】动画--两张图片轮回翻转
- 今日的第一个博客
- 数据结构基础之链表
- 求能覆盖到所有点的最少集合情况(超时题,须优化)
- HDU 4518 解题报告
- 【DP】Codeforces Round #341 (Div. 2) E
- N皇后
- 关于getline
- 走过2015,展望2016
- 安卓开发——DisplayMetrics类
- FZUOJ 1402 猪的安家 (中国剩余定理 互质)
- 每个痛苦的过程都是你进步的阶梯
- HDU 2647 Reward(拓扑排序)