求所有整数 1 到 N 的最大奇数除数之和

Find the sum of the greatest odd divisor of all integers 1 through N

本文关键字:整数      更新时间:2023-10-16

我得到一个正整数N.f(N(是N的最大奇数除数。

求和 (f(1(+f(2(+f(3(+....f(N((%m.

如果 N 是 10^18 阶,而 m 可以达到 10^9,那么更快的算法应该是什么?

暴力破解算法示例:

int sum=0;
int a[n+1];
for(int i=1;i<=n;i++){
if(i%2!=0)
a[i] = i;
else
a[i] = a[i/2];
}
for(int i=1;i<=n;i++){
sum+=a[i];
}
cout<<sum;

范围 [1,N] 中奇数的总和是奇数数数的平方,或 ((N+1(/2(^2,其中 '/' 表示整数除法。我们称之为 p(N(。

我们仍然需要找到范围 [1,N] 中偶数的最大奇数除数之和。我们可以将范围内的偶数除以除以它们的最大幂 2。

For 1 power of 2: p(N/2)
For 2 powers of 2: p(N/4)
For 3 powers of 2: p(N/8)

等。。。

即, f(N( = p(N( + p(N/2( + p(N/4( + p(N/8( + ...

以下是 N = 1, 2, ..., 20 的结果:

N,  f(N)
1,    1
2,    2
3,    5
4,    6
5,   11
6,   14
7,   21
8,   22
9,   31
10,  36
11,  47
12,  50
13,  63
14,  70
15,  85
16,  86
17, 103
18, 112
19, 131
20, 136

无耻地采用戴夫的解决方案,但添加了代码。

找到:

F(N) mod M = (f(1) + f(2) + ... + f(N)) mod M

鉴于:

1.  f(n) = greatest odd divisor of n
1a. f(n) = n, for all odd n
1b. f(n) = f(n/2), for all even n
(note, this is recursive: f(n) = f(n/2) = f(n/4) = ... until we hit an odd number)
2.  p(n) = sum of all odd numbers less than or equal to n
2a. p(n) = (number of odd numbers less than or equal to n) squared
3.  F(N) = f(1) + f(2) + ... + f(N)
4.  1 <= N <= 10^18
5.  1 <= M <= 10^9

然后:

F(N) = p(N) + [f(2) + f(4) + ... + f(largest even not > N)]
= p(N) + [f(1) + f(2) + ... + f(N/2)]
= p(N) + F(N/2)
= p(N) + p(N/2) + p(N/4) + ...
and 
F(N) mod M = (p(N) mod M + p(N/2) mod M + ...) mod M

p(N)具有复杂性O(1),递归F(N)具有复杂性O(log N)这将比可能O(N log N)的蛮力方法快得多(我相信。有人验证了这一点(。

以下C++代码完成此算法

#include <iostream>
using value_type = unsigned long long;
value_type p_N_mod_M(value_type N, value_type M)
{
// nom := _N_umber of _O_dd numbers not greater than N, _M_od-M
value_type nom = ((N + 1) / 2) % M;
return (nom * nom) % M;
}
value_type F_N_mod_M(value_type N, value_type M)
{
if (N == 0) return 0;
if (N == 1) return 1;
return (p_N_mod_M(N, M) + F_N_mod_M(N / 2, M)) % M;
}
int main()
{
value_type N, M;
std::cout << "Calculates F(N) mod M = (f(1) + f(2) + ... + f(N)) mod M,n"
"where f(n) is the greatest odd divisor of n.n"
" [1 <= N <= 10^18]; [1 <= M <= 10^9]n"
"------------------------------------------------------------------n"
"Enter N followed by M: ";
std::cin >> N >> M;
std::cout << "nF(" << N << ") mod " << M << " = " << F_N_mod_M(N, M) << "n";
}

示例输出:

Calculates F(N) mod M = (f(1) + f(2) + ... + f(N)) mod M,
where f(n) is the greatest odd divisor of n.
[1 <= N <= 10^18]; [1 <= M <= 10^9]
------------------------------------------------------------------
Enter N followed by M: 20 200
F(20) mod 200 = 136
----
Calculates F(N) mod M = (f(1) + f(2) + ... + f(N)) mod M,
where f(n) is the greatest odd divisor of n.
[1 <= N <= 10^18]; [1 <= M <= 10^9]
------------------------------------------------------------------
Enter N followed by M: 20 135
F(20) mod 135 = 1