bzoj 2186: [Sdoi2008]沙拉公主的困惑

 1 #include<cstdio>
 2 #include<iostream>
 3 #define ll long long
 4 #define N 10000009
 5 using namespace std;
 6 int jie[N],ine[N],sum[N];
 7 int T,R,n,m,tot,zhan[N];
 8 bool mark[N];
 9 void exgcd(int a1,int a2,int &x,int &y)
10 {
11     if(!a2)
12       {
13         x=1;
14         y=0;
15         return;
16       }
17     exgcd(a2,a1%a2,x,y);
18     int t=x;
19     x=y;
20     y=t-a1/a2*y;
21 }
22 int main()
23 {
24     scanf("%d%d",&T,&R);
25     jie[1]=1;
26     for(int i=2;i<=N-5;i++)
27       jie[i]=(ll)jie[i-1]*i%R;
28     for(int i=2;i<=N-5;i++)
29       {
30         if(!mark[i])
31           {
32             int y;
33             exgcd(i,R,ine[i],y);
34             ine[i]=(ine[i]+R)%R;
35             zhan[++tot]=i;
36           }
37             for(int j=1;j<=tot&&zhan[j]*i<=N;j++)
38               {
39                 mark[zhan[j]*i]=1;
40                 if(i%zhan[j]==0)
41                   break;
42               }
43     }     
44     sum[1]=1;
45     for(int i=2;i<=N-5;i++)
46       {
47         sum[i]=sum[i-1];
48         if(!mark[i])
49           sum[i]=(ll)sum[i]*(i-1)%R*ine[i]%R;
50       }
51     for(;T;T--)
52       {
53         scanf("%d%d",&n,&m);
54         printf("%d
",(ll)jie[n]*sum[m]%R);
55       }
56     return 0;
57 }

答案为n!/m!*phi(m!) 化简后就变成了n!*(p1-1)/p1*(p2-1)/p2*......

预处理n!与后面那些数,答案就可以很快求出来。当然除的话要用逆元。

原文地址:https://www.cnblogs.com/xydddd/p/5299086.html