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]\)的倍数,然后再统计两边余下部分。