2021.12.04【NOIP提高B组】模拟赛 题解

今天的比赛结束了,总体来说还不辍,但仍需改进。
那就来看下今天的题目吧。

T1 非整除序列

\((Time Limits: 1000 ms)\)
\((Memory Limits: 32768 KB)\)

Description

定义\(S(N)\)为最小的不能整除N 的正整数,接下再计算\(S(S(N))\)\(S(S(S(N)))\)
直到得到数字2。定义\(strength(N)\)为上述过程得到的序列长度。
如N=6 时得到的序列为6,4,3,2,\(strength(6)=4\)
给定两个正整数A,B,A<b,计算\(strength(a)+strength(a+1)+...+strength(b)\)

input

一行输入两个数A,B , 3<=A<b<=1017

output

输出\(strength(A)+strength(A+1)+...+strength(B)\)的值。

Sample Input

input 1:

3 6

input 2:

100 200

Sample Output

output 1:

11

output 2:

262

Data Constraint

100%的数据满足3<=A<b<=1017

题目大意及模型转换:

一张由1017个结点组成的树,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]\)的倍数,然后再统计两边余下部分。

posted @ 2021-12-04 14:28  Ethereal1072  阅读(46)  评论(0编辑  收藏  举报