【BZOJ2186】【SDoi2008】沙拉公主的困惑 数论

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

HINT

 

Source

 

Solution:这道题主要是推导和线性求逆元。
求1~N!内与M!互质的数的个数mod p。
首先,我们知道(x,y)=1=>(x,2y)=1……(其实我就不知道,我弱我自豪)
因为N!一定是M!的倍数,为什么呢,这我都知道,你说为什么。那么每找到一个与M!互质的数则有N!/M!个数与M!互质!
而M!内与其互质的数的个数不就是φ(M!)吗,而那些数又恰好是M!的质因数,那么,φ(m!)=(m!)*∏(pi-1)/pi (pi<=m),so,我们所求的就变成辣n!*∏(pi-1)/pi
看了po姐的blog十分仰慕
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #define ll long long 
 5 #define N 10000000
 6 using namespace std;
 7 int n,m,p;
 8 ll jc[10000005],prime[500500],ine[10000005],ans[10000005];
 9 bool notprime[10000005];
10 void preproce()
11 {
12     int t=0;
13     for (int i=2;i<=N;i++)
14     {
15         if (!notprime[i])   prime[++t]=i;
16         for (int j=1;j<=t&&prime[j]*i<=N;j++)
17         {
18             notprime[prime[j]*i]=1;
19             if (!i%prime[j]) break;
20             }
21     }
22     jc[1]=1;
23     for (int i=2;i<=N;i++)   jc[i]=jc[i-1]*i%p;
24     ine[1]=1;
25     for (int i=2;i<=N&&i<p;i++)   ine[i]=(p-p/i)*ine[p%i]%p;
26     ans[1]=1;
27     for (int i=2;i<=N;i++)   
28     {
29         if (!notprime[i]) ans[i]=ans[i-1]*(i-1)%p*ine[i%p]%p;
30         else    ans[i]=ans[i-1];
31     }
32 }
33 int main()
34 {
35     int T;
36     scanf("%d%d",&T,&p);
37     preproce(); 
38     while (T--)
39     {
40         scanf("%d%d",&n,&m);
41         printf("%d\n",jc[n]*ans[m]%p);
42     }
43     return 0;
44 }
View Code

 

 

你可能感兴趣的:(【BZOJ2186】【SDoi2008】沙拉公主的困惑 数论)