非整除序列
2015-08-11 16:12
260 查看
题目大意及模型转换:
一张由10^17个结点组成的树,2是根节点。编号i的父亲为j,其中满足i是1~j-1中任意一个数的倍数,但不是j的倍数。询问区间A~B,算出其中每个节点到根节点的距离和。
一种思路:
发现如果i满足父亲节点为j,那么i一定是g[j-1]的倍数,而不是g[j]的倍数。其中g[i]=lcm(1..i)。那么预处理出g数组,并得到结论:大于41的数,父亲一定小于等于41。那么好办了,可以暴力求出1~41中每个数的f值(f[i]表示i到根节点的距离),那么如果i的父亲为j,f[i]就为f[j]+1。
继续想下去:
现在,考虑枚举一个i,然后找出区间A~B有多少数的根节点为i。也就是说,要找出区间中有多少个数是g[i-1]的倍数却不是g[i]的倍数。这个不好搞,因为有两个约束。1、是g[i-1]的倍数。2、不是g[i]的倍数。我们发现g[i]一定是g[i-1]的倍数,那么不是g[i-1]的倍数,一定不是g[i]的倍数。那么同时满足两个约束的,就是不是g[i]的倍数的个数减去不是g[i-1]的倍数的个数。完全可以用h[i]表示枚举到i是找出的区间中有多少个数是g[i-1]的倍数却不是g[i]的倍数,h[i]=tmp-h[i-1]。tmp为不是g[i]的倍数的个数。
计算个数:
对于区间A~B,要找不是g[i]的倍数有多少个。我们先找出一对L~R,其中L是g[i]的倍数且L>=A,R是g[i]的倍数且R<=B。找不出满足条件的L,R,那么个数一定是B-A+1。否则,个数是B-R+L-A+(R-L)/g[i]*(g[i]-1)。易证,每g[i]个就有g[i-1]个不是g[i]的倍数,然后再统计两边余下部分。
一张由10^17个结点组成的树,2是根节点。编号i的父亲为j,其中满足i是1~j-1中任意一个数的倍数,但不是j的倍数。询问区间A~B,算出其中每个节点到根节点的距离和。
一种思路:
发现如果i满足父亲节点为j,那么i一定是g[j-1]的倍数,而不是g[j]的倍数。其中g[i]=lcm(1..i)。那么预处理出g数组,并得到结论:大于41的数,父亲一定小于等于41。那么好办了,可以暴力求出1~41中每个数的f值(f[i]表示i到根节点的距离),那么如果i的父亲为j,f[i]就为f[j]+1。
继续想下去:
现在,考虑枚举一个i,然后找出区间A~B有多少数的根节点为i。也就是说,要找出区间中有多少个数是g[i-1]的倍数却不是g[i]的倍数。这个不好搞,因为有两个约束。1、是g[i-1]的倍数。2、不是g[i]的倍数。我们发现g[i]一定是g[i-1]的倍数,那么不是g[i-1]的倍数,一定不是g[i]的倍数。那么同时满足两个约束的,就是不是g[i]的倍数的个数减去不是g[i-1]的倍数的个数。完全可以用h[i]表示枚举到i是找出的区间中有多少个数是g[i-1]的倍数却不是g[i]的倍数,h[i]=tmp-h[i-1]。tmp为不是g[i]的倍数的个数。
计算个数:
对于区间A~B,要找不是g[i]的倍数有多少个。我们先找出一对L~R,其中L是g[i]的倍数且L>=A,R是g[i]的倍数且R<=B。找不出满足条件的L,R,那么个数一定是B-A+1。否则,个数是B-R+L-A+(R-L)/g[i]*(g[i]-1)。易证,每g[i]个就有g[i-1]个不是g[i]的倍数,然后再统计两边余下部分。
相关文章推荐
- 黑马程序员——C语言笔记之循环结构
- WinpCap的详解(三)
- [LeetCode] Convert Sorted Array to Binary Search Tree
- 关于SurfaceView学习.
- 使用WampServer绑定虚拟域名
- Druid数据库连接池的简单使用
- OC NSDictionary 的常用方法
- C#操作EXCEL时,判断一个单元格是否为空的方式
- IOS界面适配二: Auto Layout的使用(上)
- Python学习第二天
- HDU 1394 Minimum Inversion Number (线段树,暴力)
- 从入门机器学习的零单排:OctaveMatlab经常使用绘图知识
- BASE64原理
- WinpCap的详解(二)
- PHP中__get()和__set()的用法实例详解
- intellij idea使用总结
- 多校-7-1005- The shortest problem
- Append data to file end
- mySQL 关于bool类型
- 22-IO流-38-IO流(File对象-常见功能-过滤器)