数学思维好题(冯哈伯公式)-平方根下取整求和
形式化题意
给定一个正整数nnn,求 ∑i=1n⌊i⌋\sum_{i=1}^{n}\left \lfloor \sqrt{i} \right \rfloor∑i=1n⌊i⌋。
题解
思路
我们可以把 111 到 nnn 分成 121^{2}12 到 22−12^{2}-122−1,222^{2}22 到 32−13^{2}-132−1……res2res^{2}res2 到 nnn 共 resresres 个部分(其中 resresres 为最大的小于等于 nnn 的整数),对于每一部分,其放法的数量都是相同的,故答案为 ∑i=1res−1((i+1)2−i2)∗i\sum_{i=1}^{res-1} ((i+1)^{2}- i^{2})*i∑i=1res−1((i+1)2−i2)∗i。暴力枚举 resresres 个部分求和,时间复杂度 O(n)O( \sqrt{n} )O(n),可得70pts。
考虑优化,resresres 可以用 sqrtsqrtsqrt 函数 O(1)O(1)O(1) 求(具体为什么是O(1)O(1)O(1)我也不清楚,是一些汇编代码的原理),那么答案即为 ∑i=1res−1((i+1)2−i2)∗i=∑i=1res−1(2i+1)∗i=∑i=1res−12i2+i=2∑i=1res−1i2+∑i=1res−1i\sum_{i=1}^{res-1} ((i+1)^{2}- i^{2})*i=\sum_{i=1}^{res-1} (2i+1)*i=\sum_{i=1}^{res-1} 2i^{2}+i=2\sum_{i=1}^{res-1} i^{2}+\sum_{i=1}^{res-1} i∑i=1res−1((i+1)2−i2)∗i=∑i=1res−1(2i+1)∗i=∑i=1res−12i2+i=2∑i=1res−1i2+∑i=1res−1i。后者可 O(1)O(1)O(1) 求出,前者也可以使用冯哈伯公式(这题如果你会这个公式可以一眼秒)O(1)O(1)O(1) 求出,总复杂度 O(1)O(1)O(1)。
图为冯哈伯公式,J.Faulhaber 在1631年的Academiae Algebrae中发表的第一个正整数的幂和通用公式。
小细节
- 除法取模记得用逆元!!!!
- 这里给出冯哈伯公式的特殊情况:自然数的平方和公式的证明
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
long long n;
int main()
{cin>>n;int l=1,r=1e9,res=0;while(l<=r) //二分res{int mid=(l+r)>>1;if(1ll*mid*mid<=n) res=mid,l=mid+1;else r=mid-1;}int ans=(n-1ll*res*res+1)%mod*res%mod;//求res*res到n之间的答案res--;//求完res*res到n之间的答案要把res--,题解中用的是(res-1),先减去再用更简单ans=(ans+2ll*res%mod*(res+1)%mod*(2ll*res%mod+1)%mod*166374059%mod)%mod;//求平方和//166374059是6的逆元,499122177是2的逆元(mod 998244353)ans=(ans+1ll*(1+res)%mod*res%mod*499122177%mod)%mod;//求一次方和//乘法可能爆int,注意用1ll*并随时取余cout<<ans;return 0;
}