题目链接:
http://poj.org/problem?id=2992
题目大意:
求解出组合数C(n,k)的约数个数。
思路:
数据中的n和k值都比较大,直接求解显然不可以。求约数个数,要先进行素因子分解。
C(n,k) = n!/(k!*(n-k)!)。n范围小于等于431,可以先筛选出431以内的素数,用数组Primer[]来存储素数。
对每个阶乘进行素因子分解,用数组jie[i][j]来表示阶乘i进行分解式第j个素数的幂。然后求组合数的素因子
分解,利用公式得到因子个数。
AC代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; bool Prime[500]; int jie[500][90]; __int64 zu[500][500]; int Primer[500],num; void GetPrime() { for(int i = 2; i <= 431; ++i) Prime[i] = true; for(int i = 2; i <= 431; ++i) { if(Prime[i]) { for(int j = i+i; j <= 431; j+=i) Prime[j] = false; } } num = 0; for(int i = 0; i <= 431; ++i) if(Prime[i]) Primer[num++] = i; } void solve() { //阶乘分解为 素因子相乘的形式jie[j][i]表示 j! 第i个素数的幂为多少 for(int i = 0;i < num; ++i) for(int j = 2; j <= 431; ++j) jie[j][i] = j/Primer[i] + jie[j/Primer[i]][i]; for(int i = 2; i <= 431; ++i) //计算因子个数 { for(int j = 1; j < i; ++j) { zu[i][j] = 1; for(int k = 0; k < num && jie[i][k]; ++k) { int side = jie[i][k] - jie[j][k] - jie[i-j][k]; //计算C(i,j)中第i个素数的幂为多少 if(side) zu[i][j] *= (side+1); //求因子个数 } } } } int main() { GetPrime(); solve(); int n,m; while(~scanf("%d%d",&n,&m)) { if(m==0 || m==n) printf("1\n"); else printf("%I64d\n",zu[n][m]); } return 0; }
原文:http://blog.csdn.net/lianai911/article/details/44598155