601 Divisibility Streaks
对于每个整数 我们可以定义一个函数 ,其中 是最小的 不能被 整除的数。比如
所以 。类似的 所以 。是满足下面两个条件的 的和 1. 2.
题目给了两个值 和 帮助验证自想法和实现。
求
首先看下 的数量级,,都接近 long
的数量级了,遍历小于 的每个数显然是不合适的。
整除 ,其实就是被 2,3,4 等整除。手算了 的情况,发现有规律的:
比如 ,那么到了 2 3 4 5 的最小公倍数往后的情况和之前的情况是一样的,循环起来了。
那么如果能计算最小公倍数以内的情况,那么就能很容易得到全部的情况。
不过事与愿违,从 2 到 32 这 31 个数的最小公倍数是一个长达 15 的数字,虽然比 小好几个数量级,但是还是不能遍历。
这条路走不通。
下面是一种直接计算的方式。
什么样的 满足 呢?,否则 。同理, 等等。
类推到 ,最后 。
对于前面 个等式被整除的数都减去 ,,得到一个统一的式子 也就是说, 是 最小公倍数的若干倍。利用这一点,可以容易的找到可能的候选 , 的数量不会很多,对于 等于 31 的情况,粗略估计也只有四位数个吧。
最后利用 得到 ,然后求和。
下面是 函数的代码
static long P(int s, long N)
{
long lcm = Enumerable.Range(1, s)
.Select(Convert.ToInt64)
.Aggregate((cur, next) => Utils.GetLcm(cur, next));
return Enumerable.Range(1, (int)((N - 2) / lcm))
.Select(i => i * lcm + 1)
.Count(c => (c + s) % (s + 1) != 0);
}
Enumerable.Range(1, s)
,多了个 1,对于最小公倍数没有影响。N-2
的原因是
调用 函数得到和