Luogu5221
Update
- 2021-02-07 这篇题解已经拖了半年了,现在开始写.
原式 \(=\prod\limits_{i=1}^n\prod\limits_{j=1}^n\dfrac{ij}{(\gcd\{i,j\})^2}=\dfrac{\prod\limits_{i=1}^n\prod\limits_{j=1}^nij}{(\prod\limits_{i=1}^n\prod\limits_{j=1}^n\gcd\{i,j\})^2}\)
对分数线上面那个柿子,
\[\prod_{i=1}^n\prod_{j=1}^nij=\prod_{i=1}^ni^nn!=(\prod_{i=1}^ni^n)(\prod_{i=1}^nn!)=(n!)^{2n}
\]
因此只要处理好分数线下面那个柿子,配合一个逆元即可.
由唯一分解定理我们知道:
\[n=\prod_{p\in P} p^a\ \ \ (a\ge0,P\ includes\ all\ the\ prime\ that's\ not\ more\ than\ n)
\]
因此
\[\prod_{i=1}^n\prod_{j=1}^n\gcd\{i,j\}=\prod_{p\in P}p^{\sum\limits_k\sum\limits_{i=1}^n\sum\limits_{j=1}^n[p^k\mid \gcd\{i,j\}]}=\prod_{p\in P}p^{\sum\limits_{k=1}^{\left\lfloor\log_pn\right\rfloor}\left\lfloor\frac{n}{p^k}\right\rfloor^2}
\]
对这个柿子暴力即可.
复杂度分析
分数线上面那个柿子 \(O(n)\) 求阶乘配合一个快速幂即可.
下面这个柿子,首先跑一遍欧拉质数筛(\(O(n)\) 线性筛).
指数上那个柿子,可以 \(O(\log n)\) 跑暴力,其值可以证明是不高于 \(n^2\) 的,因此快速幂也是 \(O(\log n)\) 的.
记 \(1\) 到 \(n\) 的质数个数为 \(\pi(n)\),则下面这个柿子的计算总复杂度应该是 \(O(\pi(n)\log n)\)?
我们知道一个柿子,
\[\pi(n)\approx\dfrac n{\ln n}
\]
因此下面这个柿子的复杂度可以看做是 \(O(n)\) 的!
逆元的复杂度并不高, 因此合并俩柿子后的总复杂度是 \(O(n)\) 的!
code:
#include <math.h>
#include <stdio.h>
#include <vector>
typedef long long llt;
typedef unsigned uint;typedef unsigned long long ullt;
typedef bool bol;typedef char chr;typedef void voi;
template<typename T>
std::vector<T>Euler_prime(T num,bol*S)//素数欧氏筛
{
std::vector<T>Ans;T len=0;Ans.clear();
for(T i=2;i<=num;i++)S[i]=true;if(num)S[0]=S[1]=false;
for(T i=2;i<=num;i++)
{
if(S[i])Ans.push_back(i),len++;
for(T j=0;j<len;j++)
{
if(Ans[j]*i>num)break;S[i*Ans[j]]=false;if(!(i%Ans[j]))break;
}
}
return Ans;
}
template<typename T>
T power_user(T base,T index,T mod)
{
T p=(index&1)?base:1,ans;if(mod)p%=mod;
if(index<=1)return p;
ans=power_user(base,index>>1,mod);
ans*=ans;if(mod)ans%=mod;
ans*=p;if(mod)ans%=mod;
return ans;
}
template<typename T>
T power(T base,T index,T mod)
{
if(mod==1)return 0;
if(!index||base==1||(mod&&base%mod==1))return mod?(1%mod):1;
if(!base||(mod&&!(base%mod)))return 0;
return power_user(mod?base%mod:base,index,mod);
}
const ullt Mod=104857601;
std::vector<uint>P;bol B[1000010];
int main()
{
uint n;ullt p,q,ans=1;scanf("%u",&n),P=Euler_prime(n,B);
for(std::vector<uint>::iterator iter=P.begin();iter!=P.end();iter++)
{
p=0,q=*iter;while(q<=n)p+=(n/q)*(n/q),p%=Mod-1,q*=*iter;ans*=power<ullt>(*iter,p,Mod),ans%=Mod;
}
ans*=ans,ans%=Mod,ans=power(ans,Mod-2,Mod),p=1;
for(uint i=2;i<=n;i++)p*=i,p%=Mod;ans*=power<ullt>(p,n<<1,Mod),ans%=Mod;
printf("%llu\n",ans);
return 0;
}
码风谔谔,请多见谅.
END
本文来自博客园,作者:myee,转载请注明原文链接:https://www.cnblogs.com/myee/p/Luogu-solution-p5221.html

浙公网安备 33010602011771号