1. 程式人生 > >【bzoj題解】2186 莎拉公主的困惑

【bzoj題解】2186 莎拉公主的困惑

ive print -m 會有 span ++i 答案 can bre

題目傳送門。

題意:求\([1,n!]\)中與\(m!\)互質的數的個數,對質數\(R\)取模,\(n\geq m\)。

答案應該等於\(\frac{n!}{m!}\phi(m!)=\frac{n!}{m!}m!\prod_{p|m!}\frac{p-1}{p}=n!\frac{\prod_{p\leq m}\,p-1}{\prod_{p\leq m}\,p}\)。

這裏\(p\)為小於等於\(m\)的質數。

所以我們處理出階乘,以及質數的乘積和對\(R\)的逆元就能得出答案。

你真的這麽想?

naive!simple!

如果\(n\geq R\),答案一定為\(0\)嗎?

可以看看這組數據:

1
3 4 3

答案為\(2\),因為\(8\,mod\,3=2\)。

但是\(4!\frac{1\cdot 2}{2\cdot 3}\)呢?\(4!=24\),而\(24\,mod\,3=0\),但是答案非\(0\)。

正確的做法是什麽?

當\(n\geq R\)時,如果\(m\geq R\)的話,\(n!\)中的因子\(R\)就有可能被分母消掉,我們應該要對\(n\geq R\)的\(n!\)消掉一個\(R\),對\(m\geq R\)的分母也消掉一個\(R\)。

這樣就不會有問題了。

代碼如下:

 1 #include<cstdio>
 2 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 3
#define F2(i,a,b) for(int i=(a);i<(b);++i) 4 int T,Mod,n,m; 5 int primes[664580], pnum=0; 6 bool isn_prime[10000001]; 7 int pi[664580],inv[10000001]; 8 int in[664580],fct[10000001]; 9 int pos[10000001]; 10 void init(){ 11 isn_prime[0]=isn_prime[1]=1; 12 F(i,2,10000000){ 13 if(!isn_prime[i]) primes[++pnum]=i; 14
for(int j=1;j<=pnum&&primes[j]*i<=10000000;++j){ 15 isn_prime[primes[j]*i]=1; 16 if(i%primes[j]==0) break; 17 } 18 } 19 inv[1]=1; for(int i=2;i<Mod&&i<=10000000;++i) 20 inv[i]=1ll*(Mod-Mod/i)*inv[Mod%i]%Mod; 21 pi[0]=1; F(i,1,pnum) pi[i]=1ll*pi[i-1]*(primes[i]-1)%Mod; 22 in[0]=1; F(i,1,pnum) if(primes[i]!=Mod) in[i]=1ll*in[i-1]*inv[primes[i]%Mod]%Mod; else in[i]=in[i-1]; 23 fct[0]=1; F(i,1,10000000) if(i!=Mod) fct[i]=1ll*fct[i-1]*i%Mod; else fct[i]=fct[i-1]; 24 F(i,2,10000000) if(isn_prime[i]) pos[i]=pos[i-1]; else pos[i]=pos[i-1]+1; 25 } 26 int main(){ 27 scanf("%d%d",&T,&Mod); 28 init(); 29 while(T--){ 30 scanf("%d%d",&n,&m); 31 if(n>=Mod&&m<Mod) puts("0"); 32 else printf("%d\n",1ll*fct[n]*pi[pos[m]]%Mod*in[pos[m]]%Mod); 33 } 34 return 0; 35 }

【bzoj題解】2186 莎拉公主的困惑