way1
这题数据 1 0 6 10^6 106,暴力枚举 i i i,然后求 i i i的中位因子,复杂度肯定不行,我们考虑到 这样一个性质, 1 0 6 10^6 106以内的数的做多因子个数240左右(打表可知),但大多数都是几十个或者更少,所以对于每个数我们可以把它因子直接给求出来,然后找中位数,对于找他的因子,不能盲目根号n去找,可以先把每个数的最小素因子和最小素因子个数找出来,然后用dfs去找,这样找出来的都是有效的,且时间也不会太多。可以均摊为每个数几十左右,然后对于查找到的直接找到num/2+1那个数,可以用nth_element这个函数求得,
way2
用
f
a
c
[
i
]
fac[i]
fac[i]表示i离根号i最近的小的那个因子。
因为最近的2个因子一定是在根号n附近,然后埃氏筛又是筛i的倍数
只要枚举的
j
j
j大于等于i的平方,就更新
f
a
c
[
j
]
=
i
fac[j] = i
fac[j]=i
因为i始终是
j
j
j的因子,只要
i
∗
i
<
=
j
i*i<=j
i∗i<=j,那么i就更新,
因为
i
i
i一直在变大,后面大的
i
i
i覆盖前面的,直到
i
∗
i
>
j
i*i>j
i∗i>j之后结束
way1_code
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 1e6+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);i++)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);i--)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
int prime[man],vis[man];
int m_prime[man],num[man];
void init(){
int cnt=0;
for(int i=2;i<man;++i){
if(!vis[i]){
prime[++cnt]=i;
m_prime[i] = i;
num[i] = 1;
}
for(int j=1;j<=cnt&&i*prime[j] < man;++j){
vis[prime[j]*i]= 1;
if(i%prime[j]==0){
m_prime[i*prime[j]] = prime[j];
num[i*prime[j]] = num[i] + 1;
break;
}
m_prime[i*prime[j]] = prime[j];
num[i*prime[j]] = 1;
}
}
}
ll p[man];
int fac[man],fac_num[man],fac1[man];
int fa_num = 0;
void dfs(int a,int dep,int n){
if(dep-1==n){
fac1[++fa_num] = a;
return;
}
for(int i = 0;i <= fac_num[dep];i++){
if(i!=0)a *= fac[dep];
dfs(a,dep+1,n);
}
}
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
init();
for(int i = 1;i < man;i++){
int tp = i;
int cnt = 0;
fa_num = 0;
fac[0] = 1;
while(tp!=1){
fac[++cnt] = m_prime[tp];
fac_num[cnt] = num[tp];
while(tp%fac[cnt]==0)tp /= fac[cnt];
}
dfs(1,0,cnt);
nth_element(fac1+1,fac1+fa_num/2+1,fac1+1+fa_num);
p[i] = (p[i-1] + (fac1[fa_num/2+1] + i / fac1[fa_num/2+1])/2)%mod;
}
int t;
cin >> t;
while(t--){
int n;cin >> n;
cout <<p[n] << endl;
}
return 0;
}
way2_code
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 1e6+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);i++)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);i--)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
int fac[man];
void init(){
for(int i = 1;i < man;i++){
for(int j = i;j < man;j += i){
if(1ll * i * i <= j)fac[j] = i;
}
}
}
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
init();
int t;
cin >> t;
while(t--){
int n;
cin >> n;
ll ans = 0;
for(int i = 1;i <= n;i++){
ans = (ans + (fac[i] + i / fac[i])/2 ) %mod;
}
cout <<ans << endl;
}
return 0;
}