第十三篇: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;
}

浙公网安备 33010602011771号