题解-bzoj2154Crash的数字表格 & bzoj2693 jzptab

Problem

bzoj2818-单组询问-无权限

bzoj2693-多组询问-需权限

洛谷1829-单组询问-无权限

(T)组询问(如果有),给定 (n,m),求

[sum_{i=1}^nsum_{j=1}^mlcm(i,j) pmod {100000009} ]

(Tleq 10^4,N,Mleq 10^7)

Solution

┗|`O′|┛ 这两题花了我一整张草稿纸啊

首先明确将(lcm)转成(gcd)会更好做:(lcm(x,y)=frac {xy}{gcd(x,y)})

套路枚举(gcd)

[Ans=sum_dfrac 1dsum_{d|a}sum_{d|b}[gcd(frac ad,frac bd)=1]ab ]

(a,b) 同时除以 (d)

[Ans=sum_d dsum_{a=1}^{frac nd}sum_{b=1}^{frac md}[gcd(a,b)=1]ab ]

想到遇到互质的情况就莫反:

设置参量 (n'=frac nd,m'=frac md)

在参量意义下,构造函数

[f(x)=sum_{a=1}^{n'}sum_{b=1}^{m'}[gcd(a,b)=x]ab\ F(x)=sum_{a=1}^{n'}sum_{b=1}^{m'}[x|gcd(a,b)]ab ]

这俩函数满足(F(x)=sum_{x|n}f(n)),根据莫反式有(f(n)=sum_{n|x}mu(frac xn)F(x))

(F(x))化简

[F(x)=sum_{x|a}^{n'}sum_{x|b}^{m'}ab=x^2(sum_{a=1}^{frac {n'}x}a)(sum_{b=1}^{frac {m'}x}b) ]

(Ans=sum_ddcdot f(1))

[f(1)=sum_dmu(d)F(d)=sum_dmu(d)d^2(sum_{a=1}^{frac {n'}d}a)(sum_{b=1}^{frac {m'}d}b) ]

首先可以明确如果预处理 (mu(d)d^2) 就可以整除分块地在 (O(sqrt n)) 的时间内算出这个式子

再接着考虑答案:(Ans=sum_ddcdot f(1)),而 (f(1)) 的参量由 (d) 决定,即应写成 (Ans=sum_ddcdot f_{frac nd,frac md}(1)),不难发现外层也能数论分块,即整个算法顶多是 (O(n))

多组询问

上面这个式子每次计算需要 (O(n)) 的时间,实测跑完 (T=10^4) 组需要 (92s),需要考虑优化

由于在单组询问时是将带入参量进行计算的,这样虽然方便但不灵活,需要将参量化出来……以下省略若干字(因为算到这里后我又用了大半张草稿纸进行拆分合并 可能是因为我喜欢用参量吧,而且听学长说这题有个简便很多的方法)

首先将原式列出来(至于为什么在整除意义下有(frac {frac ab}c=frac a{bc}),可以想想(frac ab=frac {a-(amod b)}b)):

[Ans=sum_ddigl [sum_tmu(t)t^2cdot (sum_{a=1}^{frac n{dt}}a)(sum_{b=1}^{frac m{dt}}b)igr ] ]

(T=dt,S(x)=frac {x(x+1)}2),并将式子内外翻转可得

[Ans=sum_{T=1}^nS(frac nT)S(frac mT)sum_{d|T}mu(d)d^2frac Td\=sum_{T=1}^nS(frac nT)S(frac mT)Tsum_{d|T}mu(d)d ]

设函数 (g(x)=xsum_{d|x}mu(d)d),可得 (Ans=sum_{T=1}^nS(frac nT)(frac mT)g(T)),这个东西就支持数论分块了,总体复杂度为(O(n+Qsqrt n))

至于怎么求 (g(x)),可以考虑只求 (h(x)=sum_{d|x}mu(d)d),这个东西是积性函数可以线性筛

具体地,在线性筛时,设当前筛数为 (i),质数为 (p)(k=icdot p)

  • (p|i),有 (h(k)=h(i)),因为新加入的质因子 (p)(i) 中已经出现,如果它不可能单独和其他质因子产生新的因数,而如果和其他的(p)因子在一起,(mu)函数就会为 (0),所以有(h(k)=h(i))
  • (p ot |i),有 (h(k)=h(i)h(j)),因为新加入的质因子 (p)(i) 中尚未出现,所以它和其他所有质因子产生的因数 (mu) 都会变号,而因子(p)也会相应地乘上去,至于保留原来因子的贡献,(h(p))在计算的时候会自带一个 (1)

Code

bzoj-2154

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=10001009,p=20101009;
int pri[N],is[N],u[N],tp;

inline int sm(int x){
	if(x&1)return (ll)x*(x+1>>1)%p;
	return (ll)(x>>1)*(x+1)%p;
}

inline int F(int n,int m){
	int res=0;
	for(int i=1,j;i<=n;i=j+1){
		j=min(n/(n/i),m/(m/i));
		res=(res+(ll)(u[j]-u[i-1]+p)*sm(n/i)%p *sm(m/i))%p;
	}return res;
}

int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	if(n>m)swap(n,m);u[1]=1;
	for(int i=2;i<=n;++i){
		if(!is[i])pri[++tp]=i,u[i]=-1;
		for(int j=1,k;j<=tp and (k=i*pri[j])<=n;++j){
			is[k]=1;
			if(i%pri[j]==0){u[k]=0;break;}
			u[k]=-u[i];
		}
		if(u[i]<0)u[i]=p-1;
		u[i]=(u[i-1]+(ll)i*i%p*u[i])%p;
	}
	ll ans=0;
	for(int i=1,j;i<=n;i=j+1){
		j=min(n/(n/i),m/(m/i));
		ans=(ans+(ll)(sm(j)-sm(i-1)+p)*F(n/i,m/i))%p;
	}
	printf("%lld
",ans);
	return 0;
}

bzoj-2693

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=10001009,p=100000009;
int pri[N],is[N],u[N],g[N],sm[N],tp;

int main(){
	u[1]=g[1]=1;
	for(int i=2;i<N;++i){
		if(!is[i])pri[++tp]=i,u[i]=p-1,g[i]=((ll)u[i]*i+1)%p;
		for(int j=1,k;j<=tp and (k=i*pri[j])<N;++j){
			is[k]=1;
			if(i%pri[j]==0){u[k]=0,g[k]=g[i];break;}
			u[k]=p-u[i],g[k]=(ll)g[i]*g[pri[j]]%p;
		}
		if(u[i]<0)u[i]=p-1;
	}
	
	for(int i=1;i<N;++i){
		u[i]=(u[i-1]+(ll)i*i%p*u[i])%p;
		g[i]=(g[i-1]+(ll)i*g[i])%p;
		sm[i]=(sm[i-1]+i<p?sm[i-1]+i:sm[i-1]+i-p);
	}
	
	int n,m,T;
	scanf("%d",&T);
	while(T--){
		ll ans=0;scanf("%d%d",&n,&m);
		if(n>m)swap(n,m);
		for(int i=1,j;i<=n;i=j+1){
			j=min(n/(n/i),m/(m/i));
			ans=(ans+(ll)sm[n/i]*sm[m/i]%p*(g[j]-g[i-1]+p))%p;
		}printf("%lld
",ans);
	}return 0;
}
原文地址:https://www.cnblogs.com/penth/p/10279284.html