欧拉函数-Product

Posted bcoier

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了欧拉函数-Product相关的知识,希望对你有一定的参考价值。

原题地址

先吐槽一波:凉心出题人又卡时间又卡空间

先来化简一波柿子

[prod_{i=1}^{n}prod_{j=1}^{n}frac{lcm(i,j)}{gcd(i,j)}]

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

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

先看前面的那一坨:

[prod_{i=1}^{n}prod_{j=1}^{n}i*j]

$(=prod_{i=1}^{n}(i^n*n!))(不理解可以把上述式子打开,就可以发现了)

[=(n!)^{n}*prod_{i=1}^{n}i^n]

[=(n!)^n*(n!)^n]

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

然后我们来看后面那一坨(先不看-2次方):

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

[=prod_{d=1}^{n}prod_{i=1}^{n}prod_{j=1}^{n}[gcd(i,j)==d]]

[=prod_{d=1}^{n}d^{sum_{i=1}^{n}sum_{j=1}^{n}[gcd(i,j)==d]}]

[=prod_{d=1}^{n}d^{sum_{i=1}^{frac{n}{d}}sum_{j=1}^{frac{n}{d}}[gcd(i,j)==1]}]

先只看指数:

[sum_{i=1}^{frac{n}{d}}sum_{j=1}^{frac{n}{d}}[gcd(i,j)==1]]

这不就是仪仗队吗?

所以我们只要求出啦欧拉函数前缀和,就可以用欧拉函数(O(1))算出指数了~

所以我们把柿子综合一下:

[sum[x]=sum_{i=1}^xphi(i)]

原式化为:[(n!)^{2n}*(Pi_{d=1}^{n}d^{2*sum[frac{n}{d}]-1})^{-2}]

然后我们就可以(O(nlogn))求出答案了

最后注意一下,因为欧拉函数前缀和会爆int,所以要用longlong,但是这样就会MLE,所以我们要考虑优化

根据欧拉定理,因为模数为质数,所以(phi(mod)=mod-1),所以原式我们可以进一步化为:

[(n!)^{2n}*(prod_{d=1}^{n}d^{(2*sum[frac{n}{d}]-1)\%(mod-1)})^{-2}]

这样就可以不需要longlong了

下面给出代码:

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define debug printf("Now is Line : %d
",__LINE__)
#define file(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout)
#define ll long long
#define mod 104857601
il int read()
{
    re int x=0,f=1;re char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
    return x*f;
}
#define maxn 1000000+5
int n,cnt,ans1=1,prim[80000],ans2=1,pai[maxn];
bool vis[maxn];
il int qpow(int a,ll b)
{
    int r=1;
    while(b)
    {
        if(b&1ll) r=1ll*r*a%mod;
        b>>=1ll;
        a=1ll*a*a%mod;
    }
    return r;
}
int main()
{
    n=read();
    pai[1]=1;
    for(re int i=2;i<=n;++i)
    {
        ans1=1ll*ans1*i%mod;
        if(!vis[i]) prim[++cnt]=i,pai[i]=i-1;
        for(re int j=1;j<=cnt;++j)
        {
            if(prim[j]*i>n) break;
            vis[prim[j]*i]=1;
            if(i%prim[j]==0) {pai[i*prim[j]]=pai[i]*prim[j];break;}
            pai[i*prim[j]]=pai[prim[j]]*pai[i];
        }
    }
    for(re int i=1;i<=n;++i) pai[i]=pai[i]*2+pai[i-1]%(mod-1);
    ans1=qpow(ans1,2*n);
    for(re int i=2;i<=n;++i) ans2=1ll*ans2*qpow(i,pai[n/i]-1)%mod;
    printf("%d",(1ll*ans1*qpow(1ll*ans2*ans2%mod,mod-2))%mod);
    return 0;
}

以上是关于欧拉函数-Product的主要内容,如果未能解决你的问题,请参考以下文章

R语言学习——欧拉计划(11)Largest product in a grid

E. Product Oriented Recurrence(矩阵快速幂+欧拉降幂)

Product Oriented Recurrence(Codeforces Round #566 (Div. 2)E+矩阵快速幂+欧拉降幂)

LuoguP5221 Product

欧拉函数知识点总结及代码模板及欧拉函数表

欧拉函数及代码实现