[ZJOI 2012]数列

Description

题库链接

给你一个数列 \(A\),满足递推公式
\[
A_n\left\{\begin{aligned}&0,&n=0\\&1,&n=1\\&A_\frac{n}{2},&2\mid n\\&A_{\left\lfloor\frac{n}{2}\right\rfloor}+A_{\left\lceil\frac{n}{2}\right\rceil},&\text{else}\end{aligned}\right.
\]

\(t\) 组询问,每次询问 \(A_n\) 为多少。

\(1\leq t\leq 20, 1\leq n\leq 10^{100}\)

Solution

容易发现计算 \(A_n\) 时,如果我们不断根据递推公式去运算,最后只会有 \(O(\log n)\) 种不同状态,因此我们可以直接暴力递归,然后用 map 存下已出现过的状态记忆化搜索就好了。

这题高精度不打错问题就不大。

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 100+5;

struct BIGN {
    int a[N], l;
    BIGN () {memset(a, l = 0, sizeof(a)); }
    BIGN (int x) {memset(a, 0, sizeof(a)); l = 1, a[1] = x; }
    bool operator == (const BIGN &b) const {
        if (l != b.l) return false;
        for (int i = l; i >= 1; i--)
            if (a[i] != b.a[i]) return false;
        return true;
    }
    bool operator < (const BIGN &b) const {
        if (l != b.l) return l < b.l;
        for (int i = l; i >= 1; i--)
            if (a[i] != b.a[i]) return a[i] < b.a[i];
        return false;
    }
    BIGN operator + (BIGN b) {
        BIGN ans; ans.l = max(l, b.l);
        if (l <= b.l) for (int i = l+1; i <= b.l; i++) a[i] = 0;
        if (b.l <= l) for (int i = b.l+1; i <= l; i++) b.a[i] = 0;
        for (int i = 1; i <= ans.l; i++)
            ans.a[i] = (a[i]+b.a[i]);
        ans.a[ans.l+1] = 0;
        for (int i = 1; i <= ans.l; i++)
            ans.a[i+1] += ans.a[i]/10, ans.a[i] %= 10;
        if (ans.a[ans.l+1]) ++ans.l;
        return ans;
    }
    void get() {
        char ch = getchar();
        while (ch < '0' || ch > '9') ch = getchar();
        while (ch >= '0' && ch <= '9') a[++l] = ch-'0', ch = getchar();
        reverse(a+1, a+l+1);
    }
    void put() {
        for (int i = l; i >= 1; i--) putchar(a[i]+'0');
        puts("");
    }
    BIGN div() {
        BIGN ans; ans.l = l; int m = 0;
        for (int i = l; i >= 1; i--)
            ans.a[i] = (m*10+a[i])/2, m = (m*10+a[i])%2;
        if (!ans.a[l]) --ans.l;
        return ans;
    }
} n, m;
int t;
map<BIGN, BIGN> mp;

BIGN dfs(BIGN n) {
    if (mp.count(n)) return mp[n];
    if (n == BIGN()) return BIGN();
    if (n == BIGN(1)) return BIGN(1);
    BIGN t = n.div();
    if (n.a[1]&1) return mp[n] = dfs(t)+dfs(t+BIGN(1));
    else return mp[n] = dfs(t);
    return mp[n];
}
int main() {
    scanf("%d\n", &t);
    while (t--) {
        n = BIGN(); n.get();
        dfs(n).put();
    }
    return 0;
}

原文地址:https://www.cnblogs.com/NaVi-Awson/p/12425631.html

时间: 2024-10-14 21:31:21

[ZJOI 2012]数列的相关文章

BZOJ 2656 ZJOI 2012 数列(sequence) 高精度+记忆化搜索

题目大意:定义个一序列,f[i] = f[i / 2] (i % 2 == 0);f[i] = f[i / 2] + f[i / 2 + 1] (i % 2 == 1);求这个数列的第m项(m <= 10 ^ 100) 思路:数据范围高精度没跑了.记得之前做过这个题的弱化版,似乎是没有高精度的记忆化搜索,这个题就是加个高精度. CODE: #include <map> #include <cstdio> #include <cstring> #include &l

数学 ZJOI 2012 数列

1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int maxn=110; 6 struct ExtInt{ 7 int a[maxn],len; 8 ExtInt(){ 9 memset(a,0,sizeof(a)); 10 len=1; 11 } 12 void clear(){ 13 memset(a,0,sizeof(a))

BZOJ 2657 ZJOI 2012 旅游(journey) 树的直径

题目大意:给出一个凸多边形的三角剖分图,每一个三角形代表一个城市,现在连接这个图中的两个点,问最多能够经过多少个城市. 思路:浙江都是一帮神么.. 这题给的条件简直是不知所云啊..转化十分巧妙.因为每个凸n边形经过三角剖分之后会出现n - 2个三角形,任意一条边只会成为两个城市的公共边或者整个多边形的边.不难推出两个城市的公共边是n - 3条,也就是说把公共边看成是新图的边的话,就会新图就会构成一颗树.之后就是很水的树的直径了... CODE: #include <map> #include

[ZJOI 2012]灾难

Description 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的生态灾难. 学过生物的阿米巴告诉小强,草原是一个极其稳定的生态系统.如果蚂蚱灭绝了,小鸟照样可以吃别的虫子,所以一个物种的灭绝并不一定会引发重大的灾难. 我们现在从专业一点的角度来看这个问题.我们用一种叫做食物网的有向图来描述生物之间的关系: 一个食物网有N个点,代表N种生物,如果生物x可以吃生物y,那么从y向x连一

BZOJ 2815 ZJOI 2012 灾难 动态倍增LCA

题目背景 阿米巴是小强的好朋友. 题目大意 给出一个食物链(拓扑图),定义一个生物所有的食物都灭绝了之后他自己也灭绝了.定义每种生物灭绝之后跟随着它灭绝的生物个数为这个生物的灾难值.求所有生物的灾难值. 思路 看题帽知出题人系列. fhq的题大家也知道,一般都是不可做的.于是我就去看了他的题解,发现这个题还是可做的. 定义一种灭绝树,对于任意一个子树,若这个子树的根节点灭绝,那么子树中的所有点都会灭绝.只要弄出这个树,我们就可以解决问题了. 先加一个超级食物,然后从这个点开始拓扑排序,保证处理到

[ZJOI 2012] 网络

[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2816 [算法] 对每种颜色的边建一棵LCT , 维护联通性即可 时间复杂度 : O(C * NlogN ^ 2) [代码] #include<bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 10; const int MAXC = 15; typedef long long ll; typedef long d

动态规划小练

终于意识到动规的水平差得一批了.这边开个小专题练一下. 题目列表是学长 frank_c1 的博客.这样一来可以保证质量,二来也有自己能看懂的题解. 事实上很多题意也是贺的 这里还是挂个链接吧:orz (刷新以获取数学公式) [APIO 2014] Beads and wires 题意 在达芬奇时代,有一个流行的儿童游戏称为连珠线.当然,这个游戏是关于珠子和线的.线是红色或蓝色的,珠子被编号为 $ 1 $ 到 $ n $ .这个游戏从一个珠子开始,每次会用如下方式添加一个新的珠子: $ Appen

Fibonacci 数列第 N项 O(logN)算法

时间复杂度为O( log n )的方法: 该算法使用矩阵乘法操作,使得算法时间复杂度为 O(logN) long long Fibonacci( unsigned n ) { int result[2] = {0, 1}; if(n < 2) return result[n]; long long fibOne = 0; long long fibTwo = 1; long long fibThree ; for(unsigned int i = 2; i <= n; ++ i) { fibT

【编程题目】一个数组是由一个递减数列左移若干位形成的,在这种数组中查找某一个数。☆

48.微软(运算):一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5}是由{6,5,4,3,2,1}左移两位形成的,在这种数组中查找某一个数. 我的思路: 非常麻烦:先是用二分法找最大的数的位置,再定位要找的数在哪个递减区间里,最后用普通的二分查找法找到.代码如下: /* 48.微软(运算): 一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5} 是由{6,5,4,3,2,1}左移两位形成的,在这种数组中查找某一个数. */ #include <stdi