【bzoj2186】[Sdoi2008]沙拉公主的困惑
2186: [Sdoi2008]沙拉公主的困惑
Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 3303 Solved: 1129
[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
4 2
Sample Output
1
【题解】
显然题目是求phi(m!) * ( n! / m!)
phi (m!) = m! * (p-1)/p p是m!的质因数
整理得 求 n! * (p-1)/p p是m!的质因数,即
预处理1-10000000的素数以及1-10000000的逆元。。。
都可以线性筛。。事实上只要把素数的逆元用exgcd求一求就好,其余并未用到
阶乘取模也预处理一下
——转自hzwer
这个题解写的很好,我也没什么可说的了。
最后吐槽一下:出题人丧心病狂,先卡空间,后卡时间。
所以千万不要用全局long long,后果如下:
RunID | User | Problem | Result | Memory | Time | Language | Code_Length | Submit_Time |
1690284 | songyiqun | 2186 | Accepted | 130196 kb | 6424 ms | C++/Edit | 1369 B | 2016-11-04 11:02:50 |
1690280 | songyiqun | 2186 | Time_Limit_Exceed | 130196 kb | 11788 ms | C++/Edit | 1362 B | 2016-11-04 10:57:08 |
1690274 | songyiqun | 2186 | Time_Limit_Exceed | 130196 kb | 11780 ms | C++/Edit | 1364 B | 2016-11-04 10:54:02 |
1690271 | songyiqun | 2186 | Time_Limit_Exceed | 130200 kb | 11776 ms | C++/Edit | 1380 B | 2016-11-04 10:52:34 |
1690264 | songyiqun | 2186 | Time_Limit_Exceed | 249340 kb | 11096 ms | C++/Edit | 1439 B | 2016-11-04 10:48:43 |
1690253 | songyiqun | 2186 | Time_Limit_Exceed | 249340 kb | 11576 ms | C++/Edit | 1386 B | 2016-11-04 10:37:04 |
1690246 | songyiqun | 2186 | Time_Limit_Exceed | 249340 kb | 11576 ms | C++/Edit | 1386 B | 2016-11-04 10:35:04 |
1690241 | songyiqun | 2186 | Time_Limit_Exceed | 249340 kb | 11624 ms | C++/Edit | 1361 B | 2016-11-04 10:26:29 |
1690240 | songyiqun | 2186 | Memory_Limit_Exceed | 391772 kb | 0 ms | C++/Edit | 1350 B | 2016-11-04 10:25:49 |
1690237 | songyiqun | 2186 | Memory_Limit_Exceed | 391772 kb | 0 ms | C++/Edit | 1350 B | 2016-11-04 10:23:07 |
1 /************* 2 bzoj 2186 3 by chty 4 2016.11.4 5 *************/ 6 #include<iostream> 7 #include<cstdio> 8 #include<cstdlib> 9 #include<cstring> 10 #include<ctime> 11 #include<cmath> 12 #include<algorithm> 13 using namespace std; 14 #define MAXN 10000000 15 int n,m,T,mod,cnt,prime[500010],ans[MAXN+10],fac[MAXN+10],ni[MAXN+10]; 16 bool check[MAXN+10]; 17 inline int read() 18 { 19 int x=0; char ch=getchar(); 20 while(ch<'0'||ch>'9')ch=getchar(); 21 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 22 return x; 23 } 24 void exgcd(int a,int b,int &x,int &y) 25 { 26 if(!b) {x=1; y=0; return;} 27 exgcd(b,a%b,x,y); 28 int t=x;x=y;y=t-a/b*y; 29 } 30 int find(int p) 31 { 32 int x,y; 33 exgcd(p,mod,x,y); 34 x=(x%mod+mod)%mod; 35 return x; 36 } 37 void pre() 38 { 39 fac[1]=1; ni[1]=1; 40 for(int i=2;i<=MAXN;i++) fac[i]=(long long)fac[i-1]*i%mod; 41 for(int i=2;i<=MAXN;i++) 42 { 43 if(!check[i]) prime[++cnt]=i,ni[i]=find(i); 44 for(int j=1;j<=cnt&&prime[j]*i<=MAXN;j++) 45 { 46 check[prime[j]*i]=1; 47 if(i%prime[j]==0) break; 48 } 49 } 50 ans[1]=1; 51 for(int i=2;i<=MAXN;i++) 52 { 53 ans[i]=ans[i-1]; 54 if(!check[i]) ans[i]=(long long)ans[i]*(i-1)%mod*ni[i]%mod; 55 } 56 } 57 int main() 58 { 59 T=read(); mod=read(); 60 pre(); 61 while(T--) 62 { 63 n=read(); m=read(); 64 printf("%d\n",(long long)fac[n]*ans[m]%mod); 65 } 66 return 0; 67 }