链接:https://ac.nowcoder.com/acm/contest/6015/F
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给出函数的定义如下:
f(x)是所有能够整除 x 的数(包含 1 和 x )中的中位数向下取整的大小,
g(x)=
∑
i
=
1
x
f
(
i
)
\sum_{i=1}^{x}f(i)
∑i=1xf(i)
输入描述:
输入包含多组数据,第一行为一个数字
T
(
1
≤
T
≤
10
)
T(1≤T≤10)
T(1≤T≤10) ,表示测试数据组数。
接下来是 T 组数据,每组数据为一行,包含一个整数
x
(
1
≤
x
≤
1000000
)
x(1≤x≤1000000)
x(1≤x≤1000000)
输出描述:
每组数据输出包含一个整数,表示 g(x) 的值,结果要求对 1e9+7 取模。
示例1
输入
3
1
2
3
输出
1
2
4
说明
能够整除 1 的数字有 1 ,故 f(1)=1;
能够整除 2 的数字有 1,2 所以中位数为
[
1
+
2
2
]
=
1
[\frac{1+2}{2} ] = 1
[21+2]=1故
f
(
2
)
=
1
f(2) = 1
f(2)=1;
能够整除 3 的数字有 1,3 所以中位数为
[
1
+
3
2
]
=
2
[\frac{1+3}{2}]=2
[21+3]=2 故
f
(
3
)
=
2
f(3) = 2
f(3)=2;
从而得出
g
(
1
)
=
1
,
g
(
2
)
=
2
,
g
(
3
)
=
4
g(1) = 1,g(2) = 2,g(3) = 4
g(1)=1,g(2)=2,g(3)=4 。
示例2
输入
1
1000000
输出
677045223
思路:
主要是求因数的中位数,这个筛法很巧妙,大佬给我讲的时候我一脸懵逼。。。哎,做好笔记好好学习吧
AC代码
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
const ll maxn=1e6,mod=1e9+7;
ll f[1000010],g[1000010],t,n;
int main() {
for(int i=1; i<=sqrt(maxn); i++) {
for(int j=i; j<=maxn; j+=i) {
if(f[j]*f[j] <j) f[j]=i; //这里求j的所有因数的中位数
}
}
for(int i=1; i<=maxn; i++) {
f[i]=(f[i]+i/f[i])/2; //偶数个因数的时候中位数是中间两个中位数之和除以2
g[i]=(g[i-1]+f[i])%mod;
}
cin>>t;
while(t--) {
cin>>n;
cout<<g[n]<<endl;
}
}
本文解析了牛客网上一道涉及数学和算法的题目,通过筛选法求解给定数值范围内所有数的因数中位数,进而计算g(x)的值。详细介绍了筛选法的巧妙之处,并附上AC代码实现。
2万+

被折叠的 条评论
为什么被折叠?



