acm-(数论、莫比乌斯反演、卡空间)LuoGu P5221 Product

题面
传送门
由于 ∏ i = 1 n ∏ j = 1 n l c m ( i , j ) g c d ( i , j ) = ∏ i = 1 n ∏ j = 1 n i j g c d ( i , j ) 2 = ∏ i = 1 n ∏ j = 1 n i j ∏ i = 1 n ∏ j = 1 n g c d ( i , j ) 2 \mathbf{\prod_{i=1}^n\prod_{j=1}^n\frac{lcm(i,j)}{gcd(i,j)}=\prod_{i=1}^n\prod_{j=1}^n\frac{ij}{gcd(i,j)^2}=\frac{\prod_{i=1}^n\prod_{j=1}^nij}{\prod_{i=1}^n\prod_{j=1}^ngcd(i,j)^2}} i=1nj=1ngcd(i,j)lcm(i,j)=i=1nj=1ngcd(i,j)2ij=i=1nj=1ngcd(i,j)2i=1nj=1nij,因此我们可以分成上下两部分来求,对于分子我们有 ∏ i = 1 n ∏ j = 1 n i j = ∏ i = 1 n i n ∏ j = 1 n j = ∏ i = 1 n i n n ! = ( n ! ) n ∏ i = 1 n i n = ( n ! ) n ( n ! ) n = ( n ! ) 2 n \mathbf{\prod_{i=1}^n\prod_{j=1}^nij=\prod_{i=1}^ni^n\prod_{j=1}^nj=\prod_{i=1}^ni^nn!=(n!)^n\prod_{i=1}^ni^n=(n!)^n(n!)^n=(n!)^{2n}} i=1nj=1nij=i=1ninj=1nj=i=1ninn!=(n!)ni=1nin=(n!)n(n!)n=(n!)2n
然后重头戏是下部分,类似于普通的莫比乌斯反演,我们更改枚举的对象,设 d = g c d ( i , j ) \mathbf{d=gcd(i,j)} d=gcd(i,j),我们枚举这个 d \mathbf{d} d从1~n,于是有 ∏ i = 1 n d k \mathbf{\prod_{i=1}^nd^{k}} i=1ndk,这个k使我们要确定的,它代表着在所有的 ( i , j ) \mathbf{(i,j)} (i,j)对中有多少对满足 g c d ( i , j ) = d \mathbf{gcd(i,j)=d} gcd(i,j)=d,也就是说 k = ∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) = d ] \mathbf{k=\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)=d]} k=i=1nj=1n[gcd(i,j)=d],然后根据结论基础数论学习笔记(下)第十部分6.18我们能立刻得到 k = 2 s u m φ ( ⌊ n d ⌋ ) − 1 \mathbf{k=2sum\varphi(\lfloor \frac nd\rfloor )-1} k=2sumφ(dn)1 s u m φ ( n ) \mathbf{sum\varphi(n)} sumφ(n)代表 φ \mathbf{\varphi} φ的1~n的前缀和。
然后剩下的工作就简单了,我们要计算的分母其实就是这么一个式子:
∏ d = 1 n d 2 s u m φ ( ⌊ n d ⌋ ) − 1 \mathbf{\prod_{d=1}^nd^{2sum\varphi(\lfloor \frac nd\rfloor)-1}} d=1nd2sumφ(dn)1,
显然我们可以对这个式子的 2 s u m φ ( ⌊ n d ⌋ ) − 1 \mathbf{2sum\varphi(\lfloor \frac nd\rfloor)-1} 2sumφ(dn)1这个部分进行分块处理,然后由于这题卡空间,暴力算分块过程中l到r的阶乘即可,线性筛复杂度为 O ( n ) \mathbf{O(n)} O(n),分块由于要暴力算阶乘复杂度仍为 O ( n ) \mathbf{O(n)} O(n),故总复杂度为 O ( n ) \mathbf{O(n)} O(n),然后要注意空间,本题空间卡得很紧,线性筛的时候标记数组最好开成bitset。

const int mod = 104857601;
inline void add(int &x,int y){x+=y,x>=(mod-1)&&(x-=mod-1);}
int n,prim[maxn],tot,phi[maxn];
void init(int n){
	bitset<maxn>flag;
	phi[1]=1;
	FOR(i,2,n+1){
		if(!flag[i])prim[tot++]=i,phi[i]=i-1;
		for(register int j =0;j<tot && prim[j]*i<=n;++j){
			flag[i*prim[j]]=1;
			if(i%prim[j]==0){
				phi[i*prim[j]]=phi[i]*prim[j];
				break;
			}
			phi[i*prim[j]]=phi[i]*(prim[j]-1);
		}
	}
	FOR(i,1,n+1)add(phi[i],phi[i-1]);
}
int main(){
	rd(&n);
	init(n);
	register int i=1,j,c,a=1,b=1;
	while(i<=n){
		j=n/(n/i),c=1;
		FOR(k,i,j+1)c=1ll*c*k%mod,a=1ll*a*k%mod;
		b=1ll*b*qpow(c,4*phi[n/i]-2,mod)%mod;
		i=j+1;
	}
	a=qpow(a,2*n,mod);
	b=1ll*a*qpow(b,mod-2,mod)%mod;
	wrn(b);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值