C. Strange Function
看数据范围
O
(
n
)
O(n)
O(n) 的复杂度肯定是不行了
f
(
x
)
f(x)
f(x) 表示从
1
1
1 开始,第一个不是
x
x
x 因子的数
考虑每个数对答案的贡献,
2
2
2 的贡献值就是这些数中不是
2
2
2 的倍数的数的个数乘
2
2
2;
3
3
3 的贡献为这些数中既不是
2
2
2 的倍数又不是
3
3
3 的倍数的数乘
3
3
3
4
4
4 的贡献度就是不是
2
,
3
,
4
2,3,4
2,3,4 倍数的数乘
4
4
4
关键在于求贡献为
x
x
x 的数的个数,这个些数的特征是:是
1
,
2
,
3
,
.
.
.
,
x
−
1
1,2,3,..., x - 1
1,2,3,...,x−1 这些数的倍数, 不是
1
,
2
,
3
,
.
.
.
.
x
1,2, 3,....x
1,2,3,....x 这些数的倍数
l
c
m
(
1
,
2
,
3
,
.
.
.
,
x
)
lcm(1,2,3,...,x)
lcm(1,2,3,...,x) 比起
l
c
m
(
1
,
2
,
3
,
.
.
.
,
x
−
1
)
lcm(1,2,3,...,x-1)
lcm(1,2,3,...,x−1) 就是多了一个约束条件,
x
x
x 也是因子,用总的(一直到
x
−
1
x-1
x−1 的)减去
x
x
x 也是它因子的数,剩下的就是
x
x
x 不是因子的数。
L
c
m
Lcm
Lcm 倍增
求每个数贡献的个数的解释
感谢大佬的讲解
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = (ll)1e9 + 7;
ll lcm(ll a, ll b)
{
return a / __gcd(a, b) * b;
}
void work()
{
ll n; scanf("%lld", &n);
ll Lcm = 1;
ll ans = 0, cnt;
for(int i = 2; Lcm <= n; ++i)
{
cnt = (n / Lcm - n / lcm(Lcm, i)) % mod;// 总的-含有i为因子的,就是f(x)=i的个数
ans = (ans + cnt * i % mod) % mod;
Lcm = lcm(Lcm, i);
}
ans = (ans % mod + mod) % mod;
printf("%lld\n", ans);
}
int main()
{
int T; scanf("%d", &T);
for(int i = 1; i <= T; ++i) work();
return 0;
}