bzoj2186

首先我们看到题目要求的是1~N!内有M!互质的个数

N!>M!,而我们是知道在M!以内与M!互质的数的个数,即phi(M!)

但是M!~N!内与M!互质的数有多少个呢?

对于每个互质的数,如果我们给他都加上M!,那一定也和M!互质

所以1~N!之间与M!互质的数为phi(M!)*(N!/M!)

由于M!很大,不能有以前的方法计算,我们可以考虑用公式计算

phi(m)=m*(p1-1)/p1*(p2-1)/p2……*(pk-1)/pk pk为m的素因数

因为m!所包含的素因数只可能在1~m内,这是比较容易计算出来的

简化可得ans=N!*(p1-1)/p1*(p2-1)/p2……*(pk-1)/pk

由于这道题又牵扯到了除法取模,所以又要用到扩展欧几里得

然后这道题是坑爹的多测,我们要预处理素数表,阶乘表等等,具体见程序

 1 var a,b,d:array[0..10000000] of int64;
 2     x,y:array[0..10010] of longint;
 3     v:array[0..10000000] of boolean;
 4     prime:array[0..700010] of longint;
 5     tot,j,i,t,p,n,m:longint;
 6     r,k,ans,s:int64;
 7 
 8 procedure exgcd(a,b:int64);
 9   var z:int64;
10   begin
11     if b=0 then
12     begin
13       r:=1;
14       k:=0;
15     end
16     else begin
17       exgcd(b,a mod b);
18       z:=r;
19       r:=k;
20       k:=z-(a div b)*k;
21     end;
22   end;
23 
24 begin
25   readln(t,p);
26   for i:=1 to t do
27   begin
28     readln(x[i],y[i]);
29     if x[i]>m then m:=x[i];
30   end;
31   for i:=2 to m do   //筛素数
32   begin
33     if not v[i] then
34     begin
35       inc(tot);
36       prime[tot]:=i;
37     end;
38     for j:=1 to tot do
39     begin
40       if i*prime[j]>m then break;
41       v[i*prime[j]]:=true;
42       if i mod prime[j]=0 then break;
43     end;
44   end;
45   d[1]:=1;
46   a[1]:=1;
47   b[1]:=1;
48   for i:=2 to m do
49   begin
50     a[i]:=a[i-1];
51     b[i]:=b[i-1];
52     if not v[i] then
53     begin
54       a[i]:=a[i]*int64(i-1) mod p;
55       b[i]:=b[i]*int64(i) mod p;
56     end;
57     d[i]:=d[i-1]*int64(i) mod p;
58   end;
59   for j:=1 to t do
60   begin
61     ans:=d[x[j]]*a[y[j]] mod p;
62     exgcd(b[y[j]],p);
63     r:=(r+p) mod p;
64     writeln(ans*r mod p);
65   end;
66 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473154.html