BZOJ 2186: [Sdoi2008]沙拉公主的困惑( 数论 )

求 φ(m!) * n! / m! .

拆开得 m! * ∏ (p-1)/p * n! / m! = ∏ (p-1)/p * n!  (p|m!)

我们可以预处理出1~m的 ∏ (p-1)/p 和 n!. 注意到取模的数为质数, 那么就可以用乘法逆元和线性筛预处理前者.时间复杂度O(MAXN)-O(1)

 

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int maxn  = 10000009;

int ans[maxn], prime[maxn], fac[maxn], n, m, MOD, pn = 0;
bool check[maxn];

int power(int x, int t) {
	int ans = 1;
	for(; t; t >>= 1) {
		if(t & 1) ans = ll(x) * ans % MOD;
		x = ll(x) * x % MOD;
	}
	return ans;
}

void init() {
	memset(check, 0, sizeof check);
	fac[1] = ans[1] = 1;
	for(int i = 2; i < maxn; i++) {
		fac[i] = ll(i) * fac[i - 1] % MOD;
		ans[i] = ans[i - 1];
		if(!check[i]) {
		    prime[pn++] = i;
		    ans[i] = ll(ans[i]) * (i - 1) % MOD * power(i, MOD - 2) % MOD;
		}
		for(int j = 0; j < pn && ll(i) * prime[j] < maxn; j++) {
			check[i * prime[j]] = true;
			if(i % prime[j] == 0) break;
		}
	}
}

int main() {
	
	int T; scanf("%d%d", &T, &MOD);
	init();
	while(T--) {
		scanf("%d%d", &n, &m);
		printf("%d\n", ll(fac[n]) * ans[m] % MOD);
	}
	
	return 0;
}

 

  

 

  

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

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 1910  Solved: 621
[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

Sample Output

1

数据范围:
对于100%的数据,1 < = N , M < = 10000000

HINT

 

Source

posted @ 2015-08-28 10:38  JSZX11556  阅读(408)  评论(0编辑  收藏  举报