C. Strange Function
Let f(i) denote the minimum positive integer x such that x is not a divisor of i.
Compute ∑ i = 1 n f ( i ) \sum_{i=1}^{n} f(i) ∑i=1nf(i) modulo 1 0 9 10^9 109+7. In other words, compute f(1)+f(2)+⋯+f(n) modulo 1 0 9 10^9 109+7.
Input
The first line contains a single integer t (1≤t≤
1
0
4
10^4
104), the number of test cases. Then t cases follow.
The only line of each test case contains a single integer n (1≤n≤ 1 0 16 10^{16} 1016).
Output
For each test case, output a single integer ans, where ans=
∑
i
=
1
n
f
(
i
)
\sum_{i = 1}^{n}f(i)
∑i=1nf(i) modulo
1
0
9
10^9
109+7.
C.奇怪的功能
让 f(i) 表示最小正整数 x,使得 x 不是 i 的除数。
计算 ∑ i = 1 n f ( i ) \sum_{i=1}^{n} f(i) ∑i=1nf(i) 模 1 0 9 10^9 109 + 7。 换句话说,计算 f(1)+f(2)+⋯+f(n) 模 1 0 9 10^9 109 + 7。
输入
第一行包含一个整数 t (1≤t≤
1
0
4
10 ^4
104),即测试用例的数量。 然后是 t 个案例。
每个测试用例的唯一一行包含一个整数 n (1≤n≤ 1 0 16 10^{16} 1016)。
输出
对于每个测试用例,输出单个整数 ans,其中 ans=
∑
i
=
1
n
f
(
i
)
\sum_{i = 1}^{n}f(i)
∑i=1nf(i) modulo
1
0
9
10^9
109+7。
思想:
如果真的要从f(1)加到f(n)的话,绝对直接爆炸,所以我们需要寻找其他的方法。由于一个数n所有的除数的最小公倍数是小于等于n的,我们可以想到,题目定义f(x)是x的最小正整数,并且这个正整数不是x的除数,那么我们就枚举所有f(x) = 2的x有多少个,结果加上2 * (x的个数),所有f(x) = 3的x有多少个,结果加上3 * (x的个数)…最终我们就求得结果。值得注意的是,我们需要发现f(x)=m,m枚举到多少?想一下,当m越来越大的时候,1,2,3,4,5,…m - 1的公倍数也就很大很大了。所以其实m不是很大。
而求f(x) = 2的情况下,那些不是2的倍数的元素的f(x)就是等于2的(因为不是2的倍数的元素就不包含2这个除数)对于f(x) = 3,4,5,…同理。我们先求得2的倍数的个数,然后用n 减去 2的倍数的个数,这就是f(x) = 2的元素个数。对于f(x) = 3, 4, 5, …同理。
在1到n中,2的倍数的元素个数有n / 2个,3的倍数的元素个数有n / 3个,但是需要注意的是,有些元素会是2 和 3 的倍数,比如 6,12 等,所以假如我们需要求是3的倍数的元素个数,我们必须先把是2的倍数的元素给去除,同理,求是4的倍数的元素个数的时候要去掉是2,和3的元素。可以用最小公倍数得到,比如求4的倍数的元素个数就是n / lcm(2, 3, 4)(lcm函数是求最小公倍数的)。
求f(x) = i就是让当前集合中的个数减去是i的倍数的元素个数,先举个例子:
假如n = 14,即求f(1) + f(2) + … + f(14);
1.先将1到n的元素全列入集合,此时集合为:{1,2,3,4,5,6,7,8,9,10,11,12,13,14};
2.求出f(x) = 2的x的元素个数:因为是2的倍数的元素个数为14 / 2 = 7个,那么就有14 - 7 = 7个不是2的倍数的元素,此时f(x) = 2的x的元素个数有7个,那么ans += 2 * 7,因为不是2的倍数的元素个数已经被算入f(x) = 2中了,所以集合变为{2,4,6,8,10,12,14}
3.求出f(x) = 3的x的元素个数:因为是3的倍数而不是2的倍数的元素个数为14 / lcm(2, 3) = 14 / 6 = 2个,所以不是2的倍数也不是3的倍数的元素个数为7 - 2 = 5个,所以集合变为{2,4,8,10,14}
…
代码如下:
#include<iostream>
using namespace std;
const int p = 1e9 + 7;
long long gcd(long long a, long long b){
return b ? gcd(b, a % b) : a;
}
long long lcm(long long a, long long b)
{
return a / gcd(a, b) * b;
}
int main()
{
int t;
cin >> t;
while(t --){
long long n;
cin >> n;
int x = 2;
long long ans = 0, res = 1;
long long geshu = n;
while(res <= n){
res = lcm(res, x);
if(geshu <= 0) break;
ans += x * (geshu - n / res);
geshu = n / res;
x ++;
}
cout << ans % p << endl;
}
}