#整除分块#洛谷 3636 曲面

题目传送门


首先将 \(\sum_{i=a}^bC(i)\) 转换成 \(\sum_{i=1}^bC(i)-\sum_{i=1}^{a-1}C(i)\)

那么题目就转换成求 \(\sum_{1\leq xyz\leq n}(|x|+|y|+|z|)^2\)

三个数相乘是正数当且仅当两负一正或者全是正数,一共四种情况。

再将平方拆开可以化简成

\[4\sum_{xyz\leq n}x^2+y^2+z^2+2(xy+xz+yz) \]

考虑三个平方项是等价的,\(xy,xz,yz\)也是等价的,所以就是

\[(12\sum_{xyz\leq n}x^2)+(24\sum_{xyz\leq n}xy) \]

对于左边这一部分考虑枚举 \(x\),就可以转换成 \(\sum_{x=1}^nx^2f(\lfloor\frac{n}{x}\rfloor)\)

其中 \(f(n)=\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor\),这两个式子都可以整除分块实现。

对于右边这一部分考虑枚举 \(z\),就可以转换成
\(\sum_{z=1}^ng(\lfloor\frac{n}{z}\rfloor)\)

\[g(n)=\sum_{i=1}^ni\frac{(\lfloor\frac{n}{i}\rfloor+1)* (\lfloor\frac{n}{i}\rfloor)}{2} \]

同样也可以用整除分块实现。


代码

#include <cstdio>
using namespace std;
const int mod=10007;
const int i4=(mod+1)>>2;
const int i6=(mod+1)/6;
int l,r;
int mo(int x,int y){return x<y?x-y+mod:x-y;}
void Mo(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
int sf(int n){
	int _n=n%mod;
    return 1ll*i6*_n*(_n+1)*(_n<<1|1)%mod;
}
//1^2+2^2+...+n^2=n*(n+1)*(2n+1)/6

int query0(int n){//f(n)
	int ans=0;
	for (int l=1,r;l<=n;l=r+1)
		r=n/(n/l),Mo(ans,(r-l+1ll)*(n/l)%mod);
	return ans;
}
int query1(int n){//g(n)
	int ans=0;
	for (int l=1,r;l<=n;l=r+1)
	    r=n/(n/l),Mo(ans,i4*(1ll*(l+r)%mod*(r-l+1)%mod)*(1ll*(n/l)*(n/l+1)%mod)%mod);
	return ans;
}
int query(int n){
	int ans=0;
	for (int l=1,r;l<=n;l=r+1){
		r=n/(n/l),Mo(ans,12*mo(sf(r),sf(l-1))%mod*query0(n/l)%mod);//左边这一部分 
		Mo(ans,24*(r-l+1ll)%mod*query1(n/l)%mod);//右边这一部分
	}
	return ans;
}
int main(){
	scanf("%d%d",&l,&r);
	printf("%d",mo(query(r),query(l-1)));
	return 0;
}
posted @ 2021-09-17 20:35  lemondinosaur  阅读(51)  评论(0编辑  收藏  举报