P4917 天守阁的地板

这是 luogu P4917 的题解,只是为了方便放学习笔记里就把这篇搬过来了。QWQ

正文

首先分析题意,明显可以发现的是,如果想使最后摆成一个正方形,且用的地板最小,那这个正方形的边长就是 \(\operatorname{lcm}(a,b)\),那地板的数量就是 \(\frac{\operatorname{lcm}(a,b)}{a}\times \frac{\operatorname{lcm}(a,b)}{b}\)

现在开始推柿子。

求:

\[\prod\limits_{i=1}^n\prod\limits_{j=1}^n\frac{\operatorname{lcm}^2(i,j)}{ij} \bmod19260817 \]

首先知道 \(\operatorname{lcm}(a,b)=\frac{ab}{\gcd(a,b)}\)

\[\prod\limits_{i=1}^n\prod\limits_{j=1}^n\frac{ij}{\gcd^2(i,j)}\bmod19260817 \]

\[\frac{\prod\limits_{i=1}^n\prod\limits_{j=1}^nij}{(\prod\limits_{i=1}^n\prod\limits_{j=1}^n\gcd(i,j))^2}\bmod 19260817 \]

先看分子。

\[\prod\limits_{i=1}^n\prod\limits_{j=1}^nij \]

\[\prod\limits_{i=1}^ni^nn! \]

\[(n!)^n(n!)^n \]

\[(n!)^{2n} \]

因为这是分子,所以计算时直接对 \(19260817\) 取模就行了。

再看分母。

\[\prod\limits_{i=1}^n\prod\limits_{j=1}^n\gcd(i,j) \]

(那个平方等最后直接乘就行了)

\[\prod\limits_{i=1}^n\prod\limits_{j=1}^n\sum\limits_{d=1}^nd[\gcd(i,j)=d] \]

显然,对于任一个 \(i\)\(j\)\(\gcd(i,j)\) 有唯一确定的值,且 \([...]\) 里东西如果为假就为 \(0\),所以就用的是求和。

\[\prod\limits_{d=1}^n\prod\limits_{i=1}^n\prod\limits_{j=1}^nd[\gcd(\frac{i}{d},\frac{j}{d})=1][d|i][d|j] \]

\[\prod\limits_{d=1}^n\prod\limits_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\prod\limits_{j=1}^{\left\lfloor\frac{n}{d}\right\rfloor}d[\gcd(i,j)=1] \]

为方便,设 \(m=\left\lfloor\frac{n}{d}\right\rfloor\)

\[\prod\limits_{d=1}^nd^{\sum\limits_{i=1}^m\sum\limits_{j=1}^m[\gcd(i,j)=1]} \]

只看指数。

\[\sum\limits_{i=1}^m\sum\limits_{j=1}^m[\gcd(i,j)] \]

可以发现这和仪仗队里的柿子一模一样,但我还是小推一下。

\[2\times\sum\limits_{i=1}^m\sum\limits_{j=1}^i[\gcd(i,j)=1]-1 \]

\[2\times\sum\limits_{i=1}^m\varphi(i)-1 \]

再看:

\[d^{2\times\sum\limits_{i=1}^m\varphi(i)-1} \bmod 19260817 \]

知道 \(a^{p-1} \equiv 1\pmod p\)\(p\) 为质数且 \(\gcd(a,p)=1\))(费马小定理)。

相当于当我们求 \(2\times\sum\limits_{i=1}^n\varphi(i)-1\) 时,我们可以将其对 \(19260816\)\(19260817-1\))取余,这样我们提前求的时候就不怕爆 long long 了。QWQ

所以我们要求的就变成了:

\[\prod\limits_{d=1}^nd^{f(\left\lfloor\frac{n}{d}\right\rfloor)} \bmod 19260817 \]

\(f(x)=2\times\sum\limits_{i=1}^x\varphi(i)-1\)

如果暴力求,时间复杂度会爆炸,所以考虑优化。显然可以用数论分块优化,对于枚举的 \(\left\lfloor\frac{n}{d}\right\rfloor\),它的贡献为 \((\frac{r!}{(l-1)!})^{f(\left\lfloor\frac{n}{d}\right\rfloor)}\),所以可以再套一个快速幂即可。

再往回看,现在整体的柿子就变成了:

\[\frac{(n!)^{2n}}{(\prod\limits_{d=1}^nd^{f(\left\lfloor\frac{n}{d}\right\rfloor)})^2} \bmod 19260817 \]

所以分别求出分子和分母,记得将分母变成平方并转成逆元即可。

代码

点击查看代码
#include<bits/stdc++.h>
#define XD 114514
#define MAXN 1000010
#define ll long long
using namespace std;
const int mod=19260817;
const int mod2=19260816;//mod-1
int t,n,ans,ans1,ans2;
int fac[MAXN],phi[MAXN],num[MAXN];
//num 为欧拉函数前缀和,fac 为阶乘
vector<int> prm;
bool vis[MAXN];
void sieve(){
	phi[1]=num[1]=1;
	for(int i=2;i<=1e6;i++){
		if(!vis[i]) prm.push_back(i),phi[i]=i-1;
		num[i]=(num[i-1]+phi[i])%mod2;
		for(auto j:prm){
			if(i*j>1e6) break;
			vis[i*j]=true;
			if(i%j==0){
				phi[i*j]=phi[i]*j;break;
			}
			phi[i*j]=phi[i]*phi[j];
		}
	}
	fac[0]=1;
	for(int i=1;i<=1e6;i++) fac[i]=1ll*fac[i-1]*i%mod;
}
int power(int x,int y){//快速幂
	int nem=1;
	while(y){
		if(y&1) nem=1ll*nem*x%mod;
		x=1ll*x*x%mod;y>>=1;
	}
	return nem;
}
int inv(int x){//求逆元
	if(x==0 or x==1) return 1;
	return power(x,mod-2)%mod;
}
void calc(){//数论分块
	int r;ans2=1;
	for(int l=1;l<=n;l=r+1){
		r=n/(n/l);
		ans2=1ll*ans2*power(1ll*fac[r]*inv(fac[l-1])%mod,(2ll*num[n/l]-1)%mod2)%mod;
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	sieve();
	cin>>t;
	while(t--){
		cin>>n;
		ans1=power(fac[n],2*n);
		calc();
		ans2=1ll*ans2*ans2%mod;
		ans=1ll*ans1*inv(ans2)%mod;
		cout<<ans<<"\n";
	}
	return 0;
}
posted @ 2023-10-15 10:43  wdgm4  阅读(57)  评论(1)    收藏  举报