×

第十三篇:P2155

题解补完计划:第十三篇。

原题题面

显然,猜结论,考虑证明 \((a, b) = (a + k\times b, b)\):

令 \(g = (a, b)\),则有 $(a + k\times b, b) = g\times (x + k\times y,y) $,其中 \(a = g\times x, b = g\times y\)。

不妨设 \(d = (x+k\times y, y)\),那么有 \(d|y, d|k\times y, d|x\)。

因为 \((x,y) = 1, d|x, d|y\), 所以 \(d = 1\),\((a+k\times b, b) = g\times(x+k\times y, y) = g = (a, b)\), 证毕。

那么 \(ans = \frac{N!}{M!}\times \varphi_{M!}\),我们只需要求 \(\varphi_{M!}\)。

\(\varphi_{M!} = M!\times\prod_{i=1}^k (1-\frac{1}{p_i})\),其中,\(p_i\) 是 \(M!\) 的质因数,这个是显然的,\(O(M)\),求就行。

总时间复杂度 \(O(M)\)。

#include<bits/stdc++.h>
using namespace std;
#define N 10000005
#define intl long long
#define For(i,a,b) for(intl i=a;i<=b;i++)
#define deo(i,a,b) for(intl i=a;i>=b;i--)
intl read() {
	intl x=0,k=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch == '-') k=-1;ch=getchar();}
	while(isdigit(ch)) {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*k;
}
intl phi[N],n,m,R,f[N];
bool vis[N]; 
vector<intl> prim;
intl Fpow(intl a,intl b) {intl res=1;for(;b;b>>=1,(a*=a)%=R) if(b&1) (res *= a) %= R; return res;}
void init() {
	For(i,2,N-5) {
		if(!vis[i]) prim.push_back(i);
		for(auto x:prim) {
			if(i*x > N-5) break;
			vis[i*x] = 1;
			if(i%x == 0) break;
		}
	}
	phi[1]=phi[2]=1;
	For(i,3,N-5) {
		if(!vis[i]) phi[i] = phi[i-1]*(i-1)%R;
		else phi[i]=phi[i-1]*i%R;
	}
	f[0]=1;
	For(i,1,N-5) if(i%R) f[i] = f[i-1]*i%R; else f[i]=f[i-1];
}
int main() {
 	intl T=read();R=read();   
	init();
	while(T--) {
		n=read(),m=read();
		if(n/R > m/R) puts("0");
		else printf("%lld\n",f[n]*Fpow(f[m],R-2)%R*phi[m]%R);
	}
	return 0;
}
posted @ 2026-10-05 17:29  shiori123  阅读(4)  评论(0)    收藏  举报