[BZOJ 2186][SDOI 2008] 莎拉公主的困惑
2186: [Sdoi2008]沙拉公主的困惑
Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 4519 Solved: 1560
[Submit][Status][Discuss]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 11
4 2
Sample Output
1
数据范围:
对于100%的数据,1 < = N , M < = 10000000
题解
其实就是求 $\varphi(m!)\times \frac{n!}{m!}$
无脑筛...
给模数之后瞎**乱筛就行了...
筛完素数推阶乘, 顺便再把 $\varphi(i)/i$ 一块推出来...
但是这题数据非常不清真: 题目保证 $R$ 为质数然而数据里有 $R$ 不是素数的情况...(详见BZOJ Discuss)...
本来我用的是快速幂求逆元来推 $\varphi(i)/i$ 然后WA到死...然后只能滚回去用 $ExGCD$ 了QAQ
参考代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <iostream> 5 #include <algorithm> 6 7 const int MAXN=1e7+10; 8 9 int p; 10 int n; 11 int m; 12 int primen; 13 int ans[MAXN]; 14 int fact[MAXN]; 15 int prime[MAXN]; 16 int inverse[MAXN]; 17 18 bool visited[MAXN]; 19 20 void ExGCD(int,int,int&,int&); 21 void PreProcess(); 22 23 int main(){ 24 int t; 25 scanf("%d%d",&t,&p); 26 PreProcess(); 27 while(t--){ 28 scanf("%d%d",&n,&m); 29 printf("%d\n",1ll*fact[n]*ans[m]%p); 30 } 31 return 0; 32 } 33 34 void PreProcess(){ 35 int x,y; 36 fact[1]=1; 37 for(int i=2;i<MAXN;i++){ 38 fact[i]=1ll*fact[i-1]*i%p; 39 } 40 inverse[1]=1; 41 for(int i=2;i<MAXN;i++){ 42 if(!visited[i]){ 43 ExGCD(i,p,x,y); 44 inverse[i]=(x%p+p)%p; 45 for(int j=i+i;j<MAXN&&j>0;j+=i){ 46 visited[j]=true; 47 } 48 } 49 } 50 ans[1]=1; 51 for(int i=2;i<MAXN;i++){ 52 ans[i]=ans[i-1]; 53 if(!visited[i]) 54 ans[i]=1ll*ans[i]*(i-1)%p*inverse[i]%p; 55 } 56 } 57 58 void ExGCD(int a,int b,int& x,int& y){ 59 if(b==0){ 60 x=1; 61 y=0; 62 return; 63 } 64 else{ 65 ExGCD(b,a%b,x,y); 66 int tmp=x; 67 x=y; 68 y=tmp-a/b*y; 69 } 70 }
本博客已弃用, 新个人主页: https://rvalue.moe, 新博客: https://blog.rvalue.moe