Description
Your task in this problem is to determine the number of divisors of Cnk. Just for fun -- or do you need any special reason for such a useful computation?
Input
The input consists of several instances. Each instance consists of a single line containing two integers n and k (0 ≤ k ≤ n ≤ 431), separated by a single space.
Output
For each instance, output a line containing exactly one integer -- the number of distinct divisors of Cnk. For the input instances, this number does not exceed 263 - 1.
Sample Input
5 1 6 3 10 4
Sample Output
2 6 16
Source
题目大意:求组合数Cnk因子的个数
如果用暴力的做法肯定会TLE的, 那么该怎么做呢?
定理1, 设f(N) 为N因子的个数 , pi为质因子, ai为该质因子的个数
把N质因数分解得到 N = p1^a1 * p2^a2 * p3^a3*……*pi^ai
f(N) = (a1 + 1)*(a2 + 1) * (a3 + 1)*……*(ai + 1);
那么怎么求N! 呢
定理2,设每个质因子指数的个数为ei, ei = [N/pi] + [N/(pi^2)] +[N/(pi^3)] +……+[N/(pi^i)] 直到 N/(pi^i) = 0
f(N!) = (e1 + 1)*(e2 + 1) *(e3 + 1)*……*(ei + 1)
Cnk = n! / (k! * (n - k)!)
首先打个素数表, 遍历一遍即可
#include <iostream> #include <sstream> #include <fstream> #include <string> #include <vector> #include <deque> #include <queue> #include <stack> #include <set> #include <map> #include <algorithm> #include <functional> #include <utility> #include <bitset> #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> #include <cstring> using namespace std; typedef long long int ll; typedef pair<int, int> P; int read() { int x=0,f=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘) { if(ch==‘-‘)f=-1; ch=getchar(); } while(ch>=‘0‘&&ch<=‘9‘) { x=x*10+ch-‘0‘; ch=getchar(); } return x*f; } const double pi=3.14159265358979323846264338327950288L; const double eps=1e-6; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; const int INT = 0x7fffffff; const int MAXN = 433; const int xi[] = {0, 0, 1, -1}; const int yi[] = {1, -1, 0, 0}; int N, T; int a[MAXN], cnt;//cnt记录素数的个数 void init() {//求素数 cnt = 0; for(int i = 2; i <=431 ; i++) { int flag = 1; for(int j = 2; j*j <= i; j++) { if(i%j == 0) { flag = 0; break; } } if(flag) { a[cnt++] = i; } } } inline int cal(int n, int k){//计算指数的个数 if(n < k) return 0; return n/k + cal(n/k, k); } int main() { init(); int n, k; while(~scanf("%d%d", &n, &k)){ ll res = 1LL; for(int i = 0; i < cnt; i++){//遍历 res *= 1LL*(cal(n, a[i]) - cal(k, a[i]) - cal(n-k, a[i]) + 1); } printf("%lld\n", res); } return 0; }