luogu P2155 [SDOI2008]沙拉公主的困惑

背景:

寫一下最近做的題目。

題目傳送門:

https://www.luogu.org/problem/P2155

題意:

[1,n!][1,n!]內與m!m!互質的數的個數。

思路:

這個轉化還是比較妙的。

考慮[1,m!][1,m!]內與m!m!互質的數的個數,顯然答案爲ϕ(m!)\phi(m!)

考慮(m!,n!](m!,n!]內與m!m!互質的數的個數。
考慮更相減損術:gcd(a,b)=gcd(a+b,b)\gcd(a,b)=\gcd(a+b,b),因此想到gcd(a,m!)=gcd(a+m!,m!)=1\gcd(a,m!)=\gcd(a+m!,m!)=1,因此相當於將ϕ(m!)\phi(m!)n!m!\frac{n!}{m!}倍。

綜上ans=n!m!ϕ(m!)ans=\frac{n!}{m!}\phi(m!)
怎麼求呢。
n!m!ϕ(m!)\frac{n!}{m!}\phi(m!)

=n!m!m!i=1k(11pi)=\frac{n!}{m!}m!\prod_{i=1}^{k}(1-\frac{1}{p_i})

=n!i=1kpi1pi=n!\prod_{i=1}^{k}\frac{p_i-1}{p_i}

這個又怎麼做呢?
n!n!直接預處理即可。
fn=i=1kp1pf_n=\prod_{i=1}^{k}\frac{p-1}{p}
後面的考慮我們已經求出了faf_a,那麼faprime=faprime1primef_{a*prime}=f_a*\frac{prime-1}{prime},由於我們可以預處理逆元,因此可以Θ(1)\Theta(1)轉移。
因爲pip_i的指數必須爲11,因此我們可以從小到大來做。

實測n<rn<r,不然對於沒有逆元n=kr,kN+n=kr,k∈N_+的,直接做會有問題,詳細處理方法可以見題解。

代碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define R register
using namespace std;
	int n,m,mod;
	int prime[1000010],fac[10000010],f[10000010],inv[10000010];
	bool bz[10000010];
void init(int ma)
{
	int t=0;
	bz[0]=bz[1]=true;
	for(R int i=2;i<=ma;i++)
	{
		if(!bz[i]) prime[++t]=i;
		for(R int j=1;j<=t&&i*prime[j]<=ma;j++)
		{
			bz[i*prime[j]]=true;
			if(!(i%prime[j])) break;
		}
	}
	fac[0]=1;
	for(R int i=1;i<=ma;i++)
		fac[i]=(LL)fac[i-1]*i%mod;
	inv[0]=inv[1]=1;
	for(R int i=2;i<=min(ma,mod-1);i++)
		inv[i]=((LL)mod-mod/i)*inv[mod%i]%mod;
	f[1]=1;
	for(R int i=2;i<=ma;i++)
	{
		f[i]=f[i-1];
		if(!bz[i]) f[i]=(LL)f[i]*inv[i]%mod*(i-1)%mod;
	}
}
int main()
{
	int T;
	scanf("%d %d",&T,&mod);
	init(10000000);
	while(T--)
	{
		scanf("%d %d",&n,&m);
		printf("%d\n",(LL)fac[n]*f[m]%mod);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章