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

卧槽,这也坑,Wikioi竟然有两个点的R不是质数。。。。。。

还好BZOJ上没有坑,其实打扩展欧几里得比i^(r-2)要快,但是既然他是质数,我当然要好好利用一下了

就是m!*φ(n)/n!,然后预处理m!和φ(n)/n!就行了

 const
maxn=;
maxq=;
var
t,r,max,tot:longint;
flag:array[..maxn]of boolean;
a,b:array[..maxn]of int64;
n,m:array[..maxq]of longint;
p:array[..]of longint;
x,y:int64; procedure extendedgcd(a,b:longint);
var
t:int64;
begin
if b= then
begin
x:=;
y:=;
exit;
end;
extendedgcd(b,a mod b);
t:=x;
x:=y;
y:=t-(a div b)*y;
end; procedure pre;
var
i,j:longint;
begin
for i:= to max do
begin
if flag[i]=false then
begin
inc(tot);
p[tot]:=i;
end;
for j:= to tot do
begin
if int64(i)*p[j]>max then break;
flag[i*p[j]]:=true;
if i mod p[j]= then break;
end;
end;
a[]:=;
b[]:=;
flag[]:=true;
for i:= to max do
begin
a[i]:=a[i-]*i mod r;
if flag[i] then b[i]:=b[i-]
else
begin
extendedgcd(i,r);
if x< then x:=x+trunc(x/r)*r+r;
x:=x mod r;
b[i]:=(b[i-]*(i-)mod r)*x mod r;
end;
end;
end; procedure main;
var
i:longint;
begin
read(t,r);
for i:= to t do
begin
read(n[i],m[i]);
if n[i]>max then max:=n[i];
end;
pre;
for i:= to t do
writeln(a[n[i]]*b[m[i]] mod r);
end; begin
main;
end.
04-29 21:02