luoguP5221 Product

Product

题目背景

\({\rm CYJian}\):"听说\(gcd\)\(\sum\)套起来比较好玩??那我就......"

题目描述

\({\rm CYJian}\)最近闲的玩起了\(gcd\)。。他想到了一个非常简单而有意思的式子:

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

\({\rm CYJian}\)已经算出来这个式子的值了。现在请你帮他验算一下吧。\({\rm CYJian}\)只给你\(0.2s\)的时间哦。

2024.5.11 upd: 放宽时空限制。

输入格式

一行一个正整数\(N\)

输出格式

一行一个正整数,表示答案模\(104857601\)的值。

样例 #1

样例输入 #1

5

样例输出 #1

585494

提示

样例解释:

\(\frac{lcm}{gcd}\) 1 2 3 4 5
1 1 2 3 4 5
2 2 1 6 2 10
3 3 6 1 12 15
4 4 2 12 1 20
5 5 10 15 20 1

对于\(30\%\)的数据:\(1 \leq N \leq 5000\)

对于\(100\%\)的数据:\(1 \leq N \leq 1000000\)

原式\(=\displaystyle\prod_{i=1}^{n}\displaystyle\prod_{j=1}^{n}\frac{i*j}{gcd(i,j)^2}\)
直接拆开,由于是乘法不是加法,算了两部分直接成绩来即可

原式\(=(\displaystyle\prod_{i=1}^{n}\displaystyle\prod_{j=1}^{n}{i*j})\times(\displaystyle\prod_{i=1}^{n}\displaystyle\prod_{j=1}^{n}\frac{1}{gcd(i,j)^2})\)
前面的部分明显很好算,看看后面的部分。
\((\displaystyle\prod_{i=1}^{n}\displaystyle\prod_{j=1}^ngcd(i,j))^{-2}\),只需要考虑里面的部分怎么搞。
\(\displaystyle\prod_{i=1}^{n}\displaystyle\prod_{j=1}^ngcd(i,j)\)经典反演套路,枚举\(d=gcd(i,j)\)并且提前,得到原式\(=\displaystyle\prod_d^{n}d^{\displaystyle\sum_{i=1}^{n}\displaystyle\sum_{j=1}^{n}[gcd(i,j)=d]}\)
那其实要算的就变成了\(\displaystyle\sum_{i=1}^{n}\displaystyle\sum_{j=1}^{n}[gcd(i,j)=d]\)
莫反板子题吧
还是写完吧,好分析复杂度。
\(\displaystyle\sum_{i=1}^{n}\displaystyle\sum_{j=1}^{n}[gcd(i,j)=d]\\ = \displaystyle\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\displaystyle\sum_{j=1}^{\lfloor\frac{n}{d}\rfloor}[gcd(i,j)=1]\)

\([gcd(i,j)=1]=\displaystyle\sum_{e|gcd(i,j)}\mu(e)\),上式变为\(\displaystyle\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\displaystyle\sum_{j=1}^{\lfloor\frac{n}{d}\rfloor}\displaystyle\sum_{e|gcd(i,j)}\mu(e)\)
\(e\)提前,变为\(\displaystyle\sum_{e=1}^{\lfloor\frac nd\rfloor}\mu(e)\displaystyle\sum_{i=1}^{\lfloor\frac{n}{de}\rfloor}\displaystyle\sum_{j=1}^{\lfloor\frac{n}{de}\rfloor}=\displaystyle\sum_{e=1}^{\lfloor\frac nd\rfloor}\mu(e)\times\lfloor\frac n {de}\rfloor^2\)

后面的直接整除分块,这个式子是\(O(\sqrt n)\)
然后算上枚举\(d\)\(O(n\sqrt n)\)\(n=1e6\)。。。
应该是前面的部分也整除分块计算,\(\displaystyle\prod_d^{n}{d^{\displaystyle\sum_{e=1}^{\lfloor\frac nd\rfloor}\mu(e)\times\lfloor\frac n {de}\rfloor^2}}\)
完全没法算啊。哦,直接算就好了。。。后面的循环是调和级数。疑似不用整除分块。。
再看看前面的部分,\(\displaystyle\prod_{i=1}^{n}\displaystyle\prod_{j=1}^{n}{i*j}\),很明显,这中间连一个加号都没有,顺序随便换。我们对于每个数字\(1\leq i\leq n\)考虑它出现过几次。
很容易发现是\(2\times n\)次,所以这个部分其实等于\({(n!)}^{{(2n)}}\)
那么便是结束了。

总体复杂度\(O(n\ln n)\)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=1e6+10;
const ll Mod=104857601;
inline ll read(){
	ll a=0,b=1;char c=getchar();
	for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
	for(;c>='0'&&c<='9';c=getchar())a=a*10+c-'0';
	return a*b;
}
ll n;
ll prim[N+1],cnt,vis[N+1],mu[N+1],phi[N+1];
void init()
{
	mu[1]=phi[1]=1;//先用筛法算出较小的部分
	for(ll i=2;i<=N;i++)
	{
		if(vis[i]==0)prim[++cnt]=i,mu[i]=-1,phi[i]=i-1;
		for(ll j=1;j<=cnt&&prim[j]*i<=N;j++)
		{
			vis[prim[j]*i]=1;
			if(i%prim[j]==0)
			{
				phi[i*prim[j]]=phi[i]*prim[j];
				mu[i*prim[j]]=0;
				break;
			}
			phi[i*prim[j]]=phi[i]*phi[prim[j]];
			mu[i*prim[j]]=mu[i]*mu[prim[j]];
		}
	}

}
inline ll ksm(ll a,ll b)
{
    ll r=1;
    while(b)
    {
        // cout<<b<<' ';
        if(b&1ll) r=1ll*r*a%Mod;
        b>>=1;
        a=1ll*a*a%Mod;
    }
    return r;
}
int main()
{
    init();
    n=read();
    ll ans=1;
    for(ll d=1;d<=n;d++)
    {
        ll ned=0;
        for(ll e=1;e<=n/d;e++)
        {
            ned=(ned+mu[e]*(n/d/e)%(Mod-1)*(n/d/e)%(Mod-1)+(Mod-1))%(Mod-1);
        }
        ans=(ans*ksm(d,ned))%Mod;
    }
    ans=ksm(ans*ans%Mod,Mod-2);
    for(ll i=1;i<=n;i++)
    {
        ans=(ans*ksm(i,2*n))%Mod;
    }
    cout<<ans<<endl;
    return 0;
}

无敌了。。\(\mu_i\)是有可能为负数的,所以取模的时候一定要注意。。。
然后我特么的对着公式写代码写错了调了我两个小时没看出来???????????
我在玩原神吗。

posted @ 2024-11-27 14:46  HL_ZZP  阅读(2)  评论(0编辑  收藏  举报