首页 > 其他分享 >P5221 Product 题解

P5221 Product 题解

时间:2023-02-12 19:34:51浏览次数:50  
标签:lfloor Product prod 题解 phi rfloor right dfrac P5221

求:

\[\prod_{i=1}^n\prod_{j=1}^n\frac{lcm(i,j)}{gcd(i,j)}\ (\bmod\ 104857601)\\1 \leq n \leq 1000000 \]

而且这个题的时限卡在 200ms,空间卡在 7.81MB。
先推式子。

\[\prod_{i=1}^n\prod_{j=1}^n\frac{lcm(i,j)}{gcd(i,j)}\\ =\prod_{i=1}^n\prod_{j=1}^n\frac{\frac{ij}{gcd(i,j)}}{gcd(i,j)}\\ =\prod_{i=1}^n\prod_{j=1}^n\frac{ij}{gcd^2(i,j)}\\ =\dfrac{\prod_{i=1}^n\prod_{j=1}^nij}{\prod_{i=1}^n\prod_{j=1}^ngcd^2(i,j)} \]

我们分开考虑,最后用上面的答案乘下面的答案在 \(\bmod\ 104857601\) 下的逆元即可。
分别记上下的答案为 \(Ans1\),\(Ans2\)。

\[Ans1 =\prod_{i=1}^n\prod_{j=1}^nij\\ =\prod_{i=1}^ni^n\prod_{j=1}^nj\\ =\prod_{i=1}^ni^n(n!)\\ =(n!)^n\prod_{i=1}^ni^n\\ =(n!)^n\left(\prod_{i=1}^ni\right)^n\\ =(n!)^n(n!)^n\\ =(n!)^{2n}\\ \]

上半部分到此为止,开始考虑下半部分。

\[Ans2 =\prod_{i=1}^n\prod_{j=1}^ngcd^2(i,j)\\ =\left(\prod_{i=1}^n\prod_{j=1}^ngcd(i,j)\right)^2\\ =\left(\prod_{i=1}^ni\times\prod_{i=2}^n\prod_{j=1}^{i-1}gcd(i,j)\times\prod_{i=1}^{n-1}\prod_{j=i+1}^ngcd(i,j)\right)^2\\ =\left(\prod_{i=1}^ni\times\left(\prod_{i=2}^n\prod_{j=1}^{i-1}gcd(i,j)\right)^2\right)^2\\ =\left(n!\times\left(\prod_{i=2}^n\prod_{j=1}^{i-1}gcd(i,j)\right)^2\right)^2\\ \]

下面来考虑如何化简下式。

\[\prod_{i=2}^n\prod_{j=1}^{i-1}gcd(i,j) \]

分两种情况。
如果 \(i\) 和 \(j\) 互质,显然 \(gcd(i,j)=1\);如果 \(i\) 和 \(j\) 不互质,我们设 \(gcd(i,j)=g\),则 \(i=p*g\),\(j=q*g\) 且 \(gcd(p,q)=1\)。又因为 \(i>j\),所以 \(p>q\)。

因此我们由枚举所有的数对,换成枚举“互质”的数对。
具体地,\(i\) 仍然从 \(2\) 枚举到 \(n\),然后从 \([1,i-1]\) 中找到与 \(i\) 互质的 \(j\),那么我们就可以考虑这一对互质数在原式中的贡献。

所谓“贡献”,就是指所有 \(p=i,q=j\) 的数对在原式的贡献,这里的 \(p\) 和 \(q\) 是上文设出的,代表这对数是它们 \(gcd\) 的“几倍”。容易发现,只要枚举到所有的“互质数对”,由此考虑的贡献就是不重不漏的。

显然,\(1*i,1*j\),\(2*i,2*j\),\(3*i,3*j\) 等都是符合上文要求的,对原式有贡献的数对。

那么这样的数对有多少呢?如果最大的数对是 \(x*i,x*j\),则 \(x*i\leq n\),即 \(x\leq\lfloor\dfrac{n}{i}\rfloor\)

因此我们可以计算“互质数对” \(i\),\(j\) 的贡献如下:

\[\prod_{g=1}^{\lfloor\frac{n}{i}\rfloor}gcd(g*i,g*j)=\prod_{g=1}^{\lfloor\frac{n}{i}\rfloor}g*gcd(i,j)=\prod_{g=1}^{n/i}g=\lfloor\dfrac{n}{i}\rfloor! \]

发现我们仍没有降低复杂度:先枚举 \(i\),再遍历所有小于 \(i\) 的,与 \(i\) 互质的数 \(j\),\(O(n^2)\)。
但我们惊喜地发现刚才计算贡献的式子与 \(j\) 无关。而且“所有小于 \(i\) 的,与 \(i\) 互质的数”的数量是固定的,即欧拉函数 \(\phi(i)\)。

再代回原式。

\[\prod_{i=2}^n\prod_{j=1}^{i-1}gcd(i,j) =\prod_{i=2}^n\prod_{j=1,i\perp j}^{i-1}\lfloor\dfrac{n}{i}\rfloor! =\prod_{i=2}^n\left(\lfloor\dfrac{n}{i}\rfloor!\right)^{\phi(i)} \]

继续回代。

\[Ans2 =\left(n!\times\left(\prod_{i=2}^n\prod_{j=1}^{i-1}gcd(i,j)\right)^2\right)^2\\ =\left(n!\times\left(\prod_{i=2}^n\left(\lfloor\dfrac{n}{i}\rfloor!\right)^{\phi(i)}\right)^2\right)^2\\ =\left(n!\times\prod_{i=2}^n\left(\lfloor\dfrac{n}{i}\rfloor!\right)^{2\phi(i)}\right)^2\\ =(n!)^2\times\prod_{i=2}^n\left(\lfloor\dfrac{n}{i}\rfloor!\right)^{2\phi(i)*2}\\ =(n!)^2\times\prod_{i=2}^n\left(\lfloor\dfrac{n}{i}\rfloor!\right)^{4\phi(i)}\\ \]

于是整个题目的答案为:

\[Ans =\dfrac{Ans1}{Ans2} =\dfrac{(n!)^{2n}}{(n!)^2\times\prod_{i=2}^n\left(\lfloor\dfrac{n}{i}\rfloor!\right)^{4\phi(i)}} \]

于是我们就可以 \(O(n)\) 地快乐计算了,最后用费马小定理求 \(Ans2\) 的逆元即可。


吗?
然后你就会收获一枚亮闪闪的 MLE。

如果根据这个式子计算,我们需要开两个数组,一个是求 \(\lfloor\dfrac{n}{i}\rfloor!\) 的阶乘数组,一个是 \(4\phi(i)\) 要用的 \(\phi\) 数组,还有欧拉筛求 \(\phi\) 所需的 \(vis\) 数组和存质数的 \(vector\)。
然而只有 7.81MB 的空间。就算我们全开 int,\(vis\) 数组用 \(bool\),\(vector\) 占用空间按照 \(\sqrt{n}\) 计算:

\[\dfrac{2*1e6*4(int)+1e6(bool)+\sqrt{1e6}(int)}{1024*1024}\approx 8.59(MB) \]

所以我们必须要优化空间。考虑优化这个部分,会发现有很多数被重复计算了。我们先尝试展开这个式子。

\[\prod_{i=2}^n\left(\lfloor\dfrac{n}{i}\rfloor!\right)^{4\phi(i)} =\prod_{i=2}^n\left(1\times2\times...\times\lfloor\dfrac{n}{i}\rfloor\right)^{4\phi(2)}\\ =1^{4\phi(2)}\times2^{4\phi(2)}\times...\times\lfloor\dfrac{n}{2}\rfloor^{4\phi(2)}\\ \times1^{4\phi(3)}\times2^{4\phi(3)}\times...\times\lfloor\dfrac{n}{3}\rfloor^{4\phi(3)}\\ \times1^{4\phi(4)}\times2^{4\phi(4)}\times...\times\lfloor\dfrac{n}{4}\rfloor^{4\phi(4)}\\ ......\\ \times1^{4\phi(\lfloor\frac{n}{2}\rfloor)}\times\lfloor\dfrac{n}{\lfloor\frac{n}{2}\rfloor}\rfloor^{4\phi(\lfloor\frac{n}{2}\rfloor)}\\ ......\\ \times1^{4\phi(n)}\\ \]

我们改变枚举顺序,原来是一行一行地枚举,现在我们一列一列地枚举。容易发现最多 \(\lfloor\dfrac{n}{2}\rfloor\) 列。
于是原式变成:

\[\prod_{i=2}^n\left(\lfloor\dfrac{n}{i}\rfloor!\right)^{4\phi(i)} =\prod_{i=1}^{\lfloor\frac{n}{2}\rfloor}i^{k_i} \]

其中 \(k_i\) 表示 \(i\) 在原式中的总次数。那么我们怎么快速求出这个 \(k_i\) 呢?

考虑再把原式换一种方式展开。

\[\prod_{i=2}^n\left(\lfloor\dfrac{n}{i}\rfloor!\right)^{4\phi(i)} =\left(\lfloor\dfrac{n}{2}\rfloor!\right)^{4\phi(2)} \times\left(\lfloor\dfrac{n}{3}\rfloor!\right)^{4\phi(3)} \times\left(\lfloor\dfrac{n}{4}\rfloor!\right)^{4\phi(4)} ... \times\left(\lfloor\dfrac{n}{n}\rfloor!\right)^{4\phi(n)} \]

显然一个数 \(x\) 在各个项里要么不出现,要么出现一次。只有当 \(\lfloor\dfrac{n}{i}\rfloor>x\) 的时候,其内才出现 \(x\)。
又因为各个项内的 \(\lfloor\dfrac{n}{i}\rfloor\) 是随 \(i\) 增大而减小的,换句话说,不增,所以一旦给定一个数 \(x\),我们就可以找到一个数 \(d=\lfloor\dfrac{n}{x}\rfloor\) 使得 \(\lfloor\dfrac{n}{2}\rfloor\) ~ \(\lfloor\dfrac{n}{d}\rfloor\) 均大于等于 \(x\),并且 \(\lfloor\dfrac{n}{d+1}\rfloor\) ~ \(\lfloor\dfrac{n}{n}\rfloor\) 均小于 \(x\)。

于是 \(x\) 出现的总次数就是 \(\lfloor\dfrac{n}{2}\rfloor!\) ~ \(\lfloor\dfrac{n}{d}\rfloor!\) 这些项的次数之和,即 \(4\phi(2)+4\phi(3)+...+4\phi(d)\)。我们设一个前缀和函数 \(S(n)=\sum_{i=2}^{d}\phi(i)\),则 \(x\) 的总次数 \(k_x\) 是 \(=4*S(d)=4*S(\dfrac{n}{x})\)。

下面给出为什么 \(d\) 等于 \(\lfloor\dfrac{n}{x}\rfloor\) 的证明。

把我们的序列提取出来,前文已经叙述,显然这是个不升的序列,如果学过数论分块下面会很好理解。

\[\lfloor\dfrac{n}{2}\rfloor,\lfloor\dfrac{n}{3}\rfloor,\lfloor\dfrac{n}{4}\rfloor,...,\lfloor\dfrac{n}{d}\rfloor,...,\lfloor\dfrac{n}{n-1}\rfloor,\lfloor\dfrac{n}{n}\rfloor \]

我们取 \(d=\lfloor\dfrac{n}{x}\rfloor\),则有 \(n=dx+r,r<x\),其实相当于带余除法。显然 \(\lfloor\dfrac{n}{d}\rfloor\geq x\)。
可以这么理解,如果取 \(d\) 的时候不取整,会导致 \(d\) 偏大,这样 \(\lfloor\dfrac{n}{d}\rfloor\) 才刚好等于 \(x\)。但取整后的 \(d\) 是小于等于不取整的 \(d\) 的,因而 \(\lfloor\dfrac{n}{d}\rfloor\) 的分母偏小,整体就会偏大。整除也不影响偏大的结果。
再证明 \(\lfloor\dfrac{n}{d+1}\rfloor<x\)。

\[\lfloor\dfrac{n}{d+1}\rfloor\\ =\lfloor\dfrac{dx+r}{d+1}\rfloor\\ =\lfloor\dfrac{dx+x+r-x}{d+1}\rfloor\\ =\lfloor\dfrac{(d+1)x+(r-x)}{d+1}\rfloor =\lfloor\dfrac{(d+1)x+(r-x)}{d+1}\rfloor =\lfloor x+\dfrac{(r-x)}{d+1}\rfloor \]

因为刚才有 \(r<x\),所以 \(r-x<0\),又因为 \(d+1>0\),所以 \(\dfrac{(r-x)}{d+1}<0\)。
\(x\) 是个整数,加上一个小于 \(0\) 的数后取整,必然是严格小于 \(x\) 的。所以:

\[d=\lfloor\dfrac{n}{x}\rfloor,\lfloor\dfrac{n}{d}\rfloor\geq x,\lfloor\dfrac{n}{d+1}\rfloor<x。 \]

至此我们已经能够求出每个数的次数 \(k_i\)。再回顾刚才的式子:

\[\prod_{i=2}^n\left(\lfloor\dfrac{n}{i}\rfloor!\right)^{4\phi(i)} =\prod_{i=1}^{\lfloor\frac{n}{2}\rfloor}i^{k_i} =\prod_{i=1}^{\lfloor\frac{n}{2}\rfloor}i^{4*S(\frac{n}{i})} \]

再回代:

\[Ans2 =(n!)^2\times\prod_{i=2}^n\left(\lfloor\dfrac{n}{i}\rfloor!\right)^{4\phi(i)} =\prod_{i=1}^{\lfloor\frac{n}{2}\rfloor}i^{4*S(\frac{n}{i})} \]

于是整个题目的答案为:

\[Ans =\dfrac{Ans1}{Ans2} =\dfrac{(n!)^{2n}}{(n!)^2\times\prod_{i=1}^{\lfloor\frac{n}{2}\rfloor}i^{4*S(\frac{n}{i})}} \]

虽然时间复杂度上只有 \(\dfrac{1}{2}\) 的常数优化,但我们发现阶乘数组已经不再需要了。\(n!\) 虽然是阶乘但不需要数组,一个变量就可存下。至于前缀和 \(S(n)\) 完全可以直接在 \(\phi(n)\) 数组上直接原地前缀和,所需空间小于 7.81MB。


至此此题做完,但有一些细节需要。注意到 \(S(n)\) 是在指数上的,而我们取前缀和的时候必定会进行取模。实际上 \(a^x\) 与 \(a^{x \bmod p}\) 在 \(\bmod p\) 意义下并不相等。有一个欧拉函数的推论如下:

\[a^x\equiv a^{x\bmod \phi(x)}(\bmod p) \]

又因为 \(p\) 为质数,\(\phi(p)\) 就等于 \(p-1\)。所以:

\[a^x\equiv a^{x\bmod p-1}(\bmod p) \]

所以在求前缀和时由模 \(p\) 改为模 \(p-1\) 即可。


代码:

// Problem: P5221 Product
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P5221
// Memory Limit: 7 MB
// Time Limit: 200 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#include <bits/extc++.h>
#define INF 0x7fffffff
#define MAXN 1000005
#define eps 1e-9
#define foru(a,b,c)	for(int a=b;a<=c;a++)
#define RT return 0;
#define db(x)	cout<<endl<<x<<endl;
#define LL long long
#define LXF int
#define RIN rin()
#define HH printf("\n")
using namespace std;
inline LXF rin(){
	LXF x=0,w=1;
	char ch=0;
	while(ch<'0'||ch>'9'){ 
	if(ch=='-') w=-1;
	ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
	x=x*10+(ch-'0');
	ch=getchar();
	}
	return x*w;
}
const LL p=104857601;
int phi[MAXN];
bitset<MAXN> vis;
vector<int> prim;
int n;
LL jc=1;
LL ksm(LL a,LL b){
	LL ret=1;
	a%=p;
	while(b){
		if(b&1)	ret=(ret*a)%p;
		b>>=1,a=(a*a)%p;
	}
	return ret;
}
void pre(){
	for(int i=2;i<=MAXN-5;i++){
		if(i<=n){
			jc=(LL)jc*(LL)i%p;
		}
		if(!vis[i]){
			prim.emplace_back(i);
			phi[i]=i-1;
		}
		for(int j=0;j<prim.size()&&i*prim[j]<=MAXN-5;j++){
			vis[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);
		}
		phi[i]=(LL)((LL)phi[i-1]+(LL)phi[i])%(p-1);//模phi(p)=p-1
	}
}
signed main(){
	n=RIN;
	pre();
	LL ans1=ksm((LL)jc,(LL)2*n),ans2=jc*jc%p;
	int top=n>>1;
	for(int i=1;i<=top;i++){
		ans2*=ksm(i,4ll*(LL)phi[n/i]);//phi是在指数上
		ans2%=p;
	}
	ans1=ans1*ksm(ans2,p-2)%p;//求Ans2逆元
	cout<<ans1;
	return 0;
}

标签:lfloor,Product,prod,题解,phi,rfloor,right,dfrac,P5221
From: https://www.cnblogs.com/Cap1taL/p/17114162.html

相关文章

  • CF1167G题解
    CF1167G题解传送门简化题意:数轴上有n个不相交且处于坐标为非负整数的单位正方形,给m个询问点,求出把这个点右侧的数轴逆时针旋转至与左侧相交时的角度。首先,碰撞时只......
  • CF1784C Monsters (hard version) 题解
    为了便于表述,下文中用"数"替代怪物的血量。我们换一种不同于easyversion中的计算答案的方法。我们先还是按照easyversion中的贪心操作来消除,当一个数能通过这种贪......
  • CF1786E题解
    容易为本题的弱化版CF1786C想出一个贪心:#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongintn,a[1000000];signedmain(){ intT; scanf("%d",&......
  • ABC268 题解
    比赛链接:https://atcoder.jp/contests/abc268/tasks题解:C对于每个盘子统计一下转那几次(3种情况)能够满足条件//bySkyRainWind#include<bits/stdc++.h>#definempr......
  • YACS 2023年1月月赛 甲组 T2 分割数列(二) 题解
    题目链接继上个月的分割数列(一)又出了这道题。首先还是考虑$n^2DP$,设$f[i]$为分到$i$个的最小权重之和。转移枚举上一个在哪里分就行了。显然时间会超限,我们考虑......
  • YACS 2023年1月月赛 甲组 T1 树的独立集 题解
    题目链接半夜12:00我不睡觉来这里更文章来了。。。这次的甲组好简单,第一次$AK$了,这题看上去很难,要求什么不挨边,其实分析一下就是树形$DP$。首先要求不挨边,所以我......
  • 题解 LGP9018【[USACO23JAN] Moo Route G】
    problem现在有一条数轴,\(t\)表示当前时刻。在\(t=0\)时Bessie恰好处在\(x=0\)的位置。接下来,每秒钟Bessie会向左或者向右移动一个单位距离,我们保证Bessie是在......
  • GitLab CICD Day 23 - 手动部署 Production 环境
    从开发到上线流程:部署到Prodvariables:user:ericpwd:Admin@1234harbor:http://172.16.128.215:8080image_hellocat:172.16.128.215:8080/hive/hellocatstages:......
  • flannel 低版本glog flag redefined error 问题解决
    最近在构建一个老版本的flannel的时候碰到了此问题,记录下,方便使用解决方法glideinstall--strip-vendor--strip-vcs参考资料https://stackoverflo......
  • go: cannot find main module, but found glide.lock 问题解决
    解决方法exportGO111MODULE=auto说明此问题主要是老golang项目构建可能会出现的,新的一般不对有此问题(都基于gomod了)参考资料https://github.co......