【BZOJ2186】[Sdoi2008]沙拉公主的困惑 線性篩素數
阿新 • • 發佈:2017-06-13
printf 兩個 stream 一個 測試 strong 幫助 zoj 編號
4 2
數據範圍:
對於100%的數據,1 < = N , M < = 10000000
【BZOJ2186】[Sdoi2008]沙拉公主的困惑
Description
大富翁國因為通貨膨脹,以及假鈔泛濫,政府決定推出一項新的政策:現有鈔票編號範圍為1到N的階乘,但是,政府只發行編號與M!互質的鈔票。房地產第一大戶沙拉公主決定預測一下大富翁國現在所有真鈔票的數量。現在,請你幫助沙拉公主解決這個問題,由於可能張數非常大,你只需計算出對R取模後的答案即可。R是一個質數。
Input
第一行為兩個整數T,R。R<=10^9+10,T<=10000,表示該組中測試數據數目,R為模後面T行,每行一對整數N,M,見題目描述 m<=n
Output
共T行,對於每一對N,M,輸出1至N!中與M!素質的數的數量對R取模後的值
Sample Input
1 114 2
Sample Output
1數據範圍:
對於100%的數據,1 < = N , M < = 10000000
題解:跟歐拉函數的求法類似,就是找出1-m中所有的素數pi,再將n!分別乘上(pi-1)/pi就行了
#include <cstdio> #include <cstring> #include <iostream> using namespace std; typedef long long ll; ll n,m,mod,T,num; int p[10010]; int pri[1000000]; int jc[10000010],jpc[10000010]; bool np[10000010]; ll pm(ll x,ll y) { ll z=1; while(y) { if(y&1) z=z*x%mod; x=x*x%mod,y>>=1; } return z; } int main() { scanf("%d%d",&T,&mod); int i,j; jc[1]=jpc[1]=1; for(i=2;i<=10000000;i++) { jc[i]=1ll*jc[i-1]*i%mod,jpc[i]=jpc[i-1]; if(!np[i]) pri[++num]=i,jpc[i]=1ll*jpc[i]*(i-1)%mod*pm(i,mod-2)%mod; for(j=1;j<=num&&1ll*i*pri[j]<=10000000;j++) { np[i*pri[j]]=1; if(i%pri[j]==0) break; } } while(T--) { scanf("%d%d",&n,&m); printf("%lld\n",1ll*jc[n]*jpc[m]%mod); } return 0; }
【BZOJ2186】[Sdoi2008]沙拉公主的困惑 線性篩素數