Before all
唉又没有时间打 CF,只好事后自己做了。。。
题目大意
定义一个函数 f ( i ) f(i) f(i) 表示不为 i i i 的因子的最小正整数,比如 f ( 1 ) = 2 , f ( 2 ) = 3 , f ( 4 ) = 3 f(1)=2,f(2)=3,f(4)=3 f(1)=2,f(2)=3,f(4)=3。现给出一个 n ( n ≤ 1 0 16 ) n(n\le 10^{16}) n(n≤1016),求 ∑ i = 1 n f ( i ) \sum_{i=1}^{n}f(i) ∑i=1nf(i) 的值 mod 1 0 9 + 7 \operatorname{mod} 10^9+7 mod109+7。
Solution
从简单开始思考,显然,所有的奇数的 f ( i ) f(i) f(i) 都是 2 2 2。所以我们来考虑偶数。
偶数必然有因子 1 , 2 1,2 1,2,所以我们暂且认为偶数的 f ( i ) = 3 f(i)=3 f(i)=3。为了接下来分析方便起见,我将偶数及其函数值打成一张表:
i i i | 2 2 2 | 4 4 4 | 6 6 6 | 8 8 8 | 10 10 10 | 12 12 12 | 14 14 14 | 16 16 16 | 18 18 18 | … \dots … |
---|---|---|---|---|---|---|---|---|---|---|
f ( i ) f(i) f(i) | 3 3 3 | 3 3 3 | 4 4 4 | 3 3 3 | 3 3 3 | 5 5 5 | 3 3 3 | 3 3 3 | 4 4 4 | … \dots … |
不难看出,每 6 6 6 个会出现一个 4 4 4,每 12 12 12 个会出现一个 5 5 5……
那么这个 6 6 6 和 12 12 12 是哪里来的呢?
我们不妨把 f ( i ) = 3 f(i)=3 f(i)=3 的偶数表示为 2 2 2,除此以外的因子都比 3 3 3 大的形式。那么 6 6 6 就是 2 × 3 2\times 3 2×3,除此以外因子都比 4 4 4 大……
所以,我们可以先打表来算这个每一个 f ( i ) f(i) f(i) 的出现周期。我们需要保证这个值是包含因子 1 , 2 , … , [ f ( i ) − 1 ] 1, 2, \dots, [f(i)-1] 1,2,…,[f(i)−1] 的最小值,设 f ( i ) − 1 f(i)-1 f(i)−1 的周期为 s s s,那么这个值只需要在 s s s 的基础上使得它能够被 f ( i ) − 1 f(i)-1 f(i)−1 整除,所以就是 f ( i ) − 1 f(i)-1 f(i)−1 和 s s s 的最小公倍数。
最后统计答案的时候,遍历每个 f ( i ) f(i) f(i) 的周期,由于我们是逐一考虑 f ( i ) f(i) f(i) 的,所以每次只要加上 ⌊ n s ⌋ \left\lfloor\dfrac{n}{s}\right\rfloor ⌊sn⌋ 即可。
Code
#include<bits/stdc++.h>
#define ll long long
#define inf (1<<30)
#define INF (1ll<<60)
using namespace std;
const ll MAXN=1e16;
const ll MOD=1e9+7;
ll top[110];
void solve(){
ll n;
scanf("%lld",&n);
ll ans=n*2%MOD;//加上奇数的值,并先把偶数的 3 加上 2
ans=(ans+n/2)%MOD;//先钦定所有偶数都是 3,由于上一行中已经加了 2,所以这里每个偶数只要 +1
for(int i=4;top[i]<=n;i++){
ans=(ans+n/top[i])%MOD;
//同理,我已经加了小 1 的值,所以这里每次只需要增加 1 就行
}
printf("%lld\n",ans);
}
ll gcd(ll x,ll y){return x%y==0?y:gcd(y,x%y);}
int main()
{
for(ll i=4,cur=2;cur<=MAXN;i++){
ll g=gcd(i-1,cur);
cur=cur*(i-1)/g;
top[i]=cur;
}//打表,top[i] 表示 f(x)=i 的周期
int T;
for(scanf("%d",&T);T--;)
solve();
return 0;
}
/*
*/