题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5587

题目大意就是初始有一个1,然后每次操作都是先在序列后面添加一个0,然后把原序列添加到0后面,然后从0到末尾,每一个都加上1。

例如:a0, a1, a2 => a0, a1, a2, 1, a0+1, a1+1, a2+1

题解中是这么说的:“

其实Ai为i二进制中1的个数。每次变化A{k+2^i}=A{k}+1,(k<2^​i​​)不产生进位,二进制1的个数加1。然后数位dp统计前m个数二进制1的个数,计算每一位对答案的贡献。只需考虑该位填1,其高位与低位的种数即可。

不过我没有想到这个。

我写了几次变换后,发现:

对最前面添加一个0,

于是每次变换长度都变成两倍,而且前后序列每一个对应差值为1。

不过这样前后二分显然对于m+1是2的次方有要求。

但是对于每2个组成一组,那么发现,至少每次变换都是以2的倍数个变换的。

也就是说单看i%2== 1的那些数ai,发现他们组成的序列变换和原序列一模一样。

i%2== 0的同理,不过需要在每一个数的基础上加上1。

然后对于s(n),自然可以由它前面i%2 == 1, i%2 == 0的两组序列构成

于是就变成了s(n) = s(n/2)+s(n/2)+n/2 or s(n/2+1)+s(n/2)+n/2(取决于n%2)

这样的话就能二分下去了,不过需要记忆化,这里采用了map进行记忆化。

不过比赛的时候,我写的是四个为一组。由于上面的n/2和n/2+1只有当大量出现n%2等于0了才能每次截掉一半。但是如果四个一组的话,每次长度变成1/4,但是最多生成n/4和n/4+1。不过这两种在不记忆化的情况下都会T。

不过用map记忆化后,我怕会MLE,本地测了好几组数据,都没有占很大内存。

代码:(二分)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>
#define LL long long using namespace std; LL m;
map<LL, LL> s; LL dfs(LL n)
{
if (n == ) return ;
if (n == ) return ;
LL ans, t1 = , t2;
if (n%)
{
if (s[n/+] == )
{
t1 = dfs(n/+);
s[n/+] = t1;
}
else t1 = s[n/+];
}
if (s[n/] == )
{
t2 = dfs(n/);
s[n/] = t2;
}
else t2 = s[n/]; ans = (n%)*t1+(-n%)*t2;
ans += n/;
return ans;
} int main()
{
//freopen("test.in", "r", stdin);
int T;
scanf("%d", &T);
for (int times = ; times <= T; ++times)
{
scanf("%I64d", &m);
LL ans;
ans = dfs(m+);
printf("%I64d\n", ans);
}
return ;
}

代码:(四分)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>
#define LL long long using namespace std; LL m;
map<LL, LL> s; LL dfs(LL n)
{
if (n == ) return ;
if (n == ) return ;
if (n == ) return ;
if (n == ) return ;
LL ans, t1 = , t2;
if (n%)
{
if (s[n/+] == )
{
t1 = dfs(n/+);
s[n/+] = t1;
}
else t1 = s[n/+];
}
if (s[n/] == )
{
t2 = dfs(n/);
s[n/] = t2;
}
else t2 = s[n/];
ans = (n%)*t1+(-n%)*t2;
ans += n/*;
if (n%) ans += n%-;
return ans;
} int main()
{
//freopen("test.in", "r", stdin);
int T;
scanf("%d", &T);
for (int times = ; times <= T; ++times)
{
//s.clear();
scanf("%I64d", &m);
LL ans;
ans = dfs(m+);
printf("%I64d\n", ans);
}
return ;
}

ACM学习历程—HDU5587 Array(数学 && 二分 && 记忆化 || 数位DP)(BestCoder Round #64 (div.2) 1003)的更多相关文章

  1. (BestCoder Round #64 (div.2))Array

    BestCoder Round #64 (div.2) Array 问题描述 Vicky是个热爱数学的魔法师,拥有复制创造的能力. 一开始他拥有一个数列{1}.每过一天,他将他当天的数列复制一遍,放在 ...

  2. ACM学习历程—SNNUOJ1215 矩阵2(二分 && dfs)

    http://219.244.176.199/JudgeOnline/problem.php?id=1215 这是这次微软和百度实习面试的一道题,题目大意就是:有一个n*m的矩阵,已知它每一行都是不严 ...

  3. ACM学习历程—SNNUOJ1214 矩阵1(二分)

    题目链接:http://219.244.176.199/JudgeOnline/problem.php?id=1214 这是这次微软实习面试的一道题,题目大意就是:有一个n*m的矩阵,已知它每一行都是 ...

  4. ACM学习历程—HDU5586 Sum(动态规划)(BestCoder Round #64 (div.2) 1002)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5586 题目大意就是把一段序列里面的数替换成f(x),然后让总和最大. 首先可以计算出初始的总和,以及每 ...

  5. ACM学习历程—HDU5585 Numbers(数论 || 大数)(BestCoder Round #64 (div.2) 1001)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5585 题目大意就是求大数是否能被2,3,5整除. 我直接上了Java大数,不过可以对末尾来判断2和5, ...

  6. ACM学习历程—CodeForces 176B Word Cut(字符串匹配 && dp && 递推)

    Description Let's consider one interesting word game. In this game you should transform one word int ...

  7. hdu5587 BestCoder Round #64 (div.2)

    问题描述 Vicky是个热爱数学的魔法师,拥有复制创造的能力. 一开始他拥有一个数列{1}.每过一天,他将他当天的数列复制一遍,放在数列尾,并在两个数列间用0隔开.Vicky想做些改变,于是他将当天新 ...

  8. 【记忆化搜索】Codeforces Round #295 (Div. 2) B - Two Buttons

    题意:给你一个数字n,有两种操作:减1或乘2,问最多经过几次操作能变成m: 随后发篇随笔普及下memset函数的初始化问题.自己也是涨了好多姿势. 代码 #include<iostream> ...

  9. 记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence

    题目传送门 /* 记忆化搜索(DP+DFS):dp[i][j] 表示第i到第j个字符,最少要加多少个括号 dp[x][x] = 1 一定要加一个括号:dp[x][y] = 0, x > y; 当 ...

随机推荐

  1. 图解堆算法、链表、栈与队列(Mark)

    原文地址: 图解堆算法.链表.栈与队列(多图预警) 堆(heap),是一类特殊的数据结构的统称.它通常被看作一棵树的数组对象.在队列中,调度程序反复提取队列中的第一个作业并运行,因为实际情况中某些时间 ...

  2. 博弈SG函数

    转自:Sprague-Grundy Function-SG函数--博弈论(3) 公平游戏的Sprague-Grundy定理 公平游戏是一种双人游戏,在游戏中双方都有完整的信息,没有牵涉,任何状态的合法 ...

  3. Windows 下Node.js开发环境配置

    第一步:安装VirtualBox(以管理员身份安装) 1.安装完成后,打开VirtualBox,点击“新建”按钮,输入信息,“下一步”(名称可任意) 2.设置内存为1024MB,“下一步”—>“ ...

  4. iostat命令简单使用

    1.iostat使用范围 iostat命令可以生成3种类型的报告: (1)CPU使用情况的报告 (2)设备使用情况的报告 (3)网络文件系统(NFS)使用情况的报告 2.每种报告的格式说明 关于CPU ...

  5. mysql导出数据或结构

    导出整个数据库结构和数据 $ mysqldump -h localhost -uroot -p123456 database > dump.sql 导出单个数据表结构和数据 $ mysqldum ...

  6. selenium java 封装

    1.简单介绍 1)展示如何封装selenium的api,使其符合我们的使用需求: 2)展示如何使用page object模式写selenium脚本: 3)展示如何即时查找元素,用以操作ajax页面: ...

  7. error in static/js/xxx.js from UglifyJs Unpected token: punc() [static/js/xxx.js]

    出现问题 使用vue+element-ui+webpack开发项目时,Jenkins构建出现报错error in static/js/xxx.js from UglifyJs Unpected tok ...

  8. border --- 透明边框

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. Data Structure Graph: strong connectivity

    如果为undirected graph就是dfs或者bfs,如果都能visit则为连通O(V+E). 如果为directed graph就先dfs或者bfs,再reverse direct,再dfs或 ...

  10. 【leetcode刷题笔记】Simplify Path

    Given an absolute path for a file (Unix-style), simplify it. For example,path = "/home/", ...