快速荷叶叶变换 fht.cpp

29 篇文章 0 订阅
1 篇文章 0 订阅

【一句话题意】求函数 f h t ( n , m ) = Σ i = 1 n Σ j = 1 m ( n &ThickSpace; m o d &ThickSpace; i ) ∗ ( m &ThickSpace; m o d &ThickSpace; j ) fht(n,m)=\Sigma^n_{i=1}\Sigma^m_{j=1}(n\;mod\;i)*(m\;mod\;j) fht(n,m)=Σi=1nΣj=1m(nmodi)(mmodj)的值。 n , m &lt; = 1 e 9 n,m&lt;=1e9 n,m<=1e9
【分析】首先拆开求和式子得到 Σ i = 1 n Σ j = 1 m ( n &ThickSpace; m o d &ThickSpace; i ) ∗ ( m &ThickSpace; m o d &ThickSpace; j ) = = Σ i = 1 n ( n &ThickSpace; m o d &ThickSpace; i ) ∗ Σ j = 1 m ( m &ThickSpace; m o d &ThickSpace; j ) \Sigma^n_{i=1}\Sigma^m_{j=1}(n\;mod\;i)*(m\;mod\;j)==\Sigma^n_{i=1}(n\;mod\;i)*\Sigma^m_{j=1}(m\;mod\;j) Σi=1nΣj=1m(nmodi)(mmodj)==Σi=1n(nmodi)Σj=1m(mmodj)
这样就可以化 O ( n m ) O(nm) O(nm)算法为 O ( n + m ) O(n+m) O(n+m)算法。但是n和m大于1e8,所以优化的程度不够,这个时候就需要优秀的数学变换。证明如下。
Σ i = 1 n ( n &ThickSpace; m o d &ThickSpace; i ) \Sigma^n_{i=1}(n\;mod\;i) Σi=1n(nmodi)
= Σ i = 1 n ( n − ⌊ n i ⌋ ∗ i ) =\Sigma^n_{i=1}(n- \lfloor \frac{n}{i}\rfloor*i) =Σi=1n(nini)
= Σ i = 1 n n − Σ i = 1 n i ∗ Σ i = 1 n ⌊ n i ⌋ =\Sigma^n_{i=1}n-\Sigma^n_{i=1 }i*\Sigma^n_{i=1}\lfloor \frac{n}{i}\rfloor =Σi=1nnΣi=1niΣi=1nin
= n 2 − n ∗ i ∗ Σ i = 1 n ⌊ n i ⌋ =n^2-n*i*\Sigma^n_{i=1}\lfloor \frac{n}{i}\rfloor =n2niΣi=1nin
一个明显的可以整除分块的式子,对于 ⌊ n i ⌋ \lfloor \frac{n}{i}\rfloor in其实只有 2 n 2\sqrt n 2n 种情况。在i小于 n \sqrt n n ⌊ n i ⌋ \lfloor \frac{n}{i}\rfloor in的值其实是不连续的,共有 n \sqrt n n 种情况。当i大于 n \sqrt n n 时, ⌊ n i ⌋ \lfloor \frac{n}{i}\rfloor in的值一定连续且只有 n \sqrt n n 种情况。
【code】

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll P=1e9+7;
ll n,m;
inline ll calc(ll x){
	ll j,s,ans=x*x;
	for (ll i=1;i<=x;i++){
		j=x/(x/i);//特别体会一下这句话,可以用参变分离证明一下j是x/i中最大的i。
		ans=ans-(i+j)*(j-i+1)/2*(x/i);
		i=j;//传递上界为下一组值的下界
	}
	return ans%P;
}
int main(){
	scanf("%lld%lld",&n,&m);
	cout<<calc(n)%P*calc(m)%P<<endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值