POJ 2992 求分子个数

题目http://poj.org/problem?id=2992

题意:求解出组合数C(n,k)的约数个数

储备知识:利用分解质因数求因子个数

如果  n = p1^a1*p2^a2...pk^ak;
那么因子个数为 (a1+1)*(a2+1)*...*(ak+1)


第一种思路:

将组合数按照分式形式把每个数进行分解,然后上下约分,最后求解。,但是死活超时。。。。

超时代码:
#include<cstring>
#include<cstdio>
using namespace std;
long long a[500],b[500];
int f[500]; 
int fi=0;

void fenjie1(int x){
	int i=1;
	while(x!=1){
		while (x%f[i]==0) {
			x=x/f[i];
			a[f[i]]++;
		}
		i++;
	}
}
void fenjie2(int x){
	int i=1;
	while(x!=1){
		while (x%f[i]==0) {
			x=x/f[i];
			b[f[i]]++;
		}
		i++;
	}
}

int main(){
	for (int i=2; i<=500; i++){
		bool b=true;
		for (int j=2; j<i; j++)
			if (i%j==0) { b=false; break; }
		if (b) {
			fi++;
			f[fi]=i;
		}
	}
	int n,k;
	while(scanf("%d%d",&n,&k) ==  2){
		long long ans=1;
	 	memset(a,0,sizeof(a));
	 	memset(b,0,sizeof(b));
	 	for (int i=n; i>n-k; i--) fenjie1(i);
	 	for (int i=1; i<=k; i++) fenjie2(i);
	 	for (int i=1; i<=n; i++)
	 		a[i]=a[i]-b[i];
		for (int i=1; i<=n; i++) 
			if (a[i]!=0) ans=ans*(a[i]+1);
	 	printf("%ld\n",ans);	
	}
}
	 	
	  

虽然这个题目这样做是超时的,但是我们的做法没有问题,问题是题目的数据组数很多。

那这样就意味着我们会分解很多很多相同的数,每次碰到都要分解,尽管之前分解过很多次了。

克服超时————记忆化一下或者提前预处理一下

先把所有能用到的数都给分解一遍 存起来,后面需要用的话直接用,就可以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()
{
    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;
}

猜你喜欢

转载自blog.csdn.net/qq_21989927/article/details/81430258