题意
f
(
i
)
=
x
f(i)=x
f(i)=x,
x
x
x为
i
i
i不能整除的最小值,题目给一个n,求解
∑
i
=
1
n
f
(
i
)
\sum_{i=1}^{n}f(i)
∑i=1nf(i)
f
(
1
)
=
2
,
f
(
2
)
=
3
,
f
(
3
)
=
2
f(1)=2,f(2)=3,f(3)=2
f(1)=2,f(2)=3,f(3)=2
解析
- 观察式子, f ( i ) = x f(i)=x f(i)=x, 1 , 2 , 3... x − 1 1,2,3...x-1 1,2,3...x−1一定能整除 i i i。
- 所以 l c m ( 1 , 2 , . . . . x − 1 ) < = i lcm(1,2,....x-1)<=i lcm(1,2,....x−1)<=i,并且 1 , 2 , . . . x − 1 1,2,...x-1 1,2,...x−1都是其因子, k ∗ l c m ( 1 , 2.... x − 1 ) = i k*lcm(1,2....x-1)=i k∗lcm(1,2....x−1)=i。
- 所以对于每个 f ( i ) = x f(i)=x f(i)=x,我们有个策略,可以去枚举 x x x,从而计算出满足 f ( i ) = x f(i)=x f(i)=x的 i i i的个数。
- 因此 i = k ∗ l c m ( 1 , 2 , . . . . x − 1 ) i=k*lcm(1,2,....x-1) i=k∗lcm(1,2,....x−1),那么我们可以枚举x,那么满足 f ( i ) = x f(i)=x f(i)=x条件的 i i i的个数就是 n l c m ( 1 , 2... x − 1 ) \frac{n}{lcm(1,2...x-1)} lcm(1,2...x−1)n。
- 但是! l c m ( 1 , . . . . x ) lcm(1,....x) lcm(1,....x)的是 l c m ( 1 , . . . x − 1 ) lcm(1,...x-1) lcm(1,...x−1)的倍数,因此我们在计算的时候,就会把后面一个也算进去,如果我们统计的数字之中 i i i,也能被 l c m ( 1 , . . . . x ) 的 lcm(1,....x)的 lcm(1,....x)的整除,那么明显 f ( i ) = x f(i)=x f(i)=x不成立,导致错误。
- 为了解决上述问题,我们需要根据容斥的思想,将结果减去 n l c m ( 1 , . . . . x ) \frac{n}{lcm(1,....x)} lcm(1,....x)n。
- 关于时间复杂度的问题,由于 l c m lcm lcm增加的很快,和 n ! n! n!有的一拼,因此很快就能得到结果,不超时。
心得
真是个好题
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,mod=1e9+7;
typedef long long ll;
ll gcd(ll a, ll b){
return b? gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
return a/gcd(a,b)*b;
}
int main(){
int t ;
cin>>t;
while(t--){
ll n ;
cin>>n;
// 枚举 f(t)=x 求t的个数 首先t是 lcm(1,2,...x-1)的倍数 我们枚举x算出t的个数
ll lc=1,ne=1,res=0;
for(int x=1;ne<=n;x++){
lc=ne;
ne=lcm(ne,x+1);
res=(res + ((x+1)%mod) * ( n/lc - n/ne )%mod)%mod;
}
cout<<res<<endl;
}
}