刚看到这个题,想到的就是i从1到n遍历,每个i出现做为因子的个数是(n/i),全部加起来就可以了
代码:
const LL mod=1000000007;
LL ans=0;
int main(){
LL n;
cin>>n;
for(int i=1;i<=n;i++){
ans+=(((n/i)*i)%mod)*i;
ans%=mod;
}
cout<<ans;
}这个时间复杂度是10^9,并且循环体里还有除法,必然是过不了的,只有30分
但是有了这个思路,我们就想到是否可以利用公式
1^2+2^2+...+n^2=n*(n+1)*(2*n+1)/6
进行优化呢?(蓝桥杯似乎很喜欢出这种公式的使用,三次方相加公式好像也出过)
利用这个公式,很容易写出这样的代码
const LL mod=1000000007;
const LL am=1000000007LL*6; //下边有解释
LL ans=0;
int main(){
LL n;
cin>>n;
LL m=n;
for(int i=1;i<=n;i++){
m=(n/i); //每次计算1~m
LL temp=(((m*(m+1))%am)*(2*m+1))%am; //计算1加到m的公式
temp/=6;
ans+=temp;
ans%=mod;
}
cout<<ans;
}因为这个公式有除以6,所以需要进行求逆元计算。有的小伙伴可能不太清楚求逆元是干什么的,简单解释一下就是,我们要计算(b/a)%m,是没办法直接((b%m)/(a%m))的,如果b是几个大数相乘,就没办法直接乘的时候取模,这时候就需要用到逆元了,我们只要求出a在m下的逆元x,则(b*x)%m=(b/a)%m,就可以计算了!逆元可以用扩展欧几里得或者快速幂计算。而这里的am是我《算法笔记》学来的,计算(b/a)%m不用求逆元,直接(b%(a*m))/a就可以得出答案(大家先别急着学这个公式,先把求逆元学会)
但是从这里我们可以看到,复杂度仍然是10^9,不过有了这两个思路,我们可以对(n/10000)以上的数字利用公式计算,然后对1~(n/10000)用第一种思路计算,这样时间复杂度就降到了10^5
#include using namespace std;
typedef long long LL;
const LL mod=1000000007;
const LL am=1000000007LL*6;
LL ans=0;
int main(){
LL n;
cin>>n;
LL m=n;
for(int i=1;i<=10000;i++){
m=(n/i);
if(m==0){ //对n小于10000的情况进行处理
cout<<ans;
return 0;
}
LL temp=(((m*(m+1))%am)*(2*m+1))%am;
temp/=6;
ans+=temp;
ans%=mod;
}
for(int i=1;i<=m;i++){
ans+=(((n/i-10000)*i)%mod)*i;
ans%=mod;
}
cout<<ans;
}但是这个代码只得了90分,这就是贪图便宜的错,(b%(a*m))/a虽然写的快,但会被一些莫名的数据卡住,所以还是要先求出逆元,再计算,下面的是一伯分代码
#include using namespace std;
typedef long long LL;
const LL mod=1000000007;
const LL ni=166666668;
LL ans=0;
int main(){
LL n;
cin>>n;
LL m=n;
for(int i=1;i<=10000;i++){
m=(n/i);
if(m==0){
cout<<ans;
return 0;
}
LL temp=(((m*(m+1))%mod)*(2*m+1))%mod;
temp*=ni;
temp%=mod;
ans+=temp;
ans%=mod;
}
for(int i=1;i<=m;i++){
ans+=(((n/i-10000)*i)%mod)*i;
ans%=mod;
}
cout<<ans;
}0.0分
5 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
mod = 1000000007 ni = 166666668 ans = 0 n = int(input()) m = n for i in range(1, 10001): m = n // i if m == 0: print(ans) exit(0) temp = ((m * (m + 1)) % mod * (2 * m + 1)) % mod temp *= ni temp %= mod ans += temp ans %= mod for i in range(1, m + 1): ans += ((n // i - 10000) * i % mod) * i ans %= mod print(ans)把博主的翻译成python了,不好意思,自己等级太低发不了题解,借个楼