您的位置:首页 > 其它

非整除序列

2015-08-11 21:18 141 查看

题意

定义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)。

3≤A<B≤10173\le A < B\le 10^{17}

分析

每个数的序列第一个数是它自己,我们要知道的就是它第二个数是什么。我们可以发现,若一个数X,它序列的第二个数为y,则X 为Py−1P_{y-1} 的倍数,且X不为PyP_{y}的倍数。其中PiP_i为2~i的所有数的最小公倍数,对于一个数PiP_i,我们可以知道区间内它的倍数有多少个。并且计算发现,ii做到41左右就会大于最大值了。

#include <cstdio>

const int N = 45;
typedef long long LL;
int f
;
LL l,r;

LL calc(LL x) {
if (x == 2) return 1;
if (x <= N) {
if (f[x]) return f[x];
for (int i = 2;i <= N;i ++) if (x % i != 0) return f[x] = calc(i) + 1;
}
for (int i = 2;i <= N;i ++) if (x % i != 0) return calc(i) + 1;
}

LL count(LL l,LL r,LL x) {
return r / x - (l - 1) / x;
}

LL gcd(LL a,LL b) {
if (b == 0) return a;
return gcd(b,a % b);
}

int main() {
scanf("%lld%lld",&l,&r);
LL last = 1,cur = 1,ans = 0;
for (LL i = 2;i <= N;i ++) {
if (last > r) break;
cur = cur * i / gcd(cur,i);
ans += (calc(i) + 1) * (count(l,r,last) - count(l,r,cur));
last = cur;
}
printf("%lld\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: