luogu2260 数论分块的板子题

今天是颓废的一天。。上午考试gg了,下午迷之困倦。。本着这个时候肝肝数学题往往有奇效的心态,

我去luogu里随便找了一道题。。然后竟然意外地弥补了一下我水弱无比的数论分块,神奇。

题解:这道题最难的就是sum(n/i * m/i *i*i)了吧。。然后这个东西我本来以为是O(n)的,但是后来想了一下,

考虑到每个n/i,m/i都是一段区间,看成4*sqrt(n)个端点在一条线段上分布,最多也只有4*sqrt(n)段,所以还是根号的。

学习了一下两个同时进行的数论分块,其实和一个的差别也不是很大。

#include<bits/stdc++.h>
using namespace std;
#define rep(x,y,z) for (int x=y; x<=z; x++)
#define downrep(x,y,z) for (int x=y; x>=z; x--)
#define ms(x,y,z) memset(x,y,sizeof(z))
#define LL long long
#define repedge(x,y) for (int x=hed[y]; ~x; x=edge[x].nex)
inline LL read(){
	LL x=0; int w=0; char ch=0;
	while (ch<'0' || ch>'9') w|=ch=='-',ch=getchar();
	while (ch>='0' && ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return w? -x:x;
}
const LL P=19940417;
LL a[15];
LL sum1(LL l,LL r){
	LL t1=l+r; LL t2=r-l+1;
	if (t1&1) t2/=2; else t1/=2;
	return ((t1%P)*(t2%P))%P;
}
LL sum2(LL n){
	a[1]=n; a[2]=n+1; a[3]=2*n+1;
	rep(i,1,3) if (!(a[i]&1)) { a[i]/=2; break;	}
	rep(i,1,3) if (!(a[i]%3)) { a[i]/=3; break;	}
	return (((((a[1]%P)*(a[2]%P))%P)*(a[3]%P))%P+P)%P;
}
LL sum(LL l,LL r){
	return ((sum2(r)-sum2(l-1))%P+P)%P;
}
LL solve(LL n,LL R){
	LL r=0; LL ans=0; R=min(n,R);
	for(LL l=1; l<=R; l=r+1){
		r=min(R,n/(n/l)); ans=(ans+sum1(l,r)*((n/l)%P))%P;
	}
	return (ans%P+P)%P;
}
LL calc(LL n,LL m,LL R){
	LL r=0; LL ans=0; R=min(n,R); R=min(m,R);
	for(LL l=1; l<=R; l=r+1){
		r=min(R,n/(n/l)); r=min(r,m/(m/l)); 
		ans=(ans+(((sum(l,r)*((n/l)%P))%P)*((m/l)%P))%P)%P;
	}   
	return (ans%P+P)%P;
}   
int main(){
	LL n=read(); LL m=read();
	LL ans=(((n%P)*(n%P))%P-solve(n,n))%P; 
	ans=(ans*((((m%P)*(m%P))%P-solve(m,m))%P))%P; 
	LL R=min(n,m); LL todec=(((((n%P)*(m%P))%P)*R)%P-(solve(n,R)*(m%P))%P-(solve(m,R)*(n%P))%P+calc(n,m,R))%P;
	ans=(ans-todec)%P; ans=(ans%P+P)%P;
	printf("%lld\n",ans);
	return 0; 
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值