nyoj 56/70(阶乘的因式分解)

阶乘因式分解(二)

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 3
描述

给定两个数n,m,其中m是一个素数。

将n(0<=n<=2^31)的阶乘分解质因数,求其中有多少个m。

注:^为求幂符号。

 

输入
第一行是一个整数s(0<s<=100),表示测试数据的组数
随后的s行, 每行有两个整数n,m。 
输出

输出m的个数


题意:将一个数n表达成多个质因数相乘,并求中质因数m出现的次数


思路1:n!=(1*2*3*4*......*(n-1)*n)=(m*2m*3m*.....*(k-1)m*km)*其他=(1*2*3*....*k)*m*其它 。其中km是最大值,km<=n所以k的最大值是n/m,所以[1,n]中有n/m个数能被n整除,然后[1,n]中每个数除以m,就剩了[1,n/m],然后继续根据上面的步骤进行运算,一直到n=0的时候结束,所得的结果和为最终的结果.

#include<stdio.h>
int main()
{
    int T,n,m,i;
    long long sum;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        sum=0;
        while(n){
            sum+=n/m;
            n=n/m;
        }
        printf("%d\n",sum);
    }
    return 0;
}


思路2(数据大会超时):

分解质因数:每个合数都可以写成几个质数相乘的形式。其中每个质数都是这个合数的因数,叫做这个合数的分解质因数。 分解质因数只针对合数。
思想: n!直接把m~n的数每个都分解看有多少个m ,然后记录下来。

#include <stdio.h>
int main()
{
    int i,j,k,m,n,s;
    scanf("%d",&s);
    while(s--)
    {
        scanf("%d%d",&n,&m);
        for(i=m,j=0;i<=n;i++)
        {
            k=i;
            while(k%m==0)
            {
                j++;
                k=k/m;

            }
        }
        printf("%d\n",j);
    }
    return 0;


思路3:

暴力因式分解
区别不大,只是把所有的质因数的个数都求出来保存到了数组里
素数的判断用到了素数筛法
优点是能记录每一个素数出现的次数

#include<cstdio>
#include<cstring>
#define N 10000
int cnt[N];
bool prime[N];
void Prim()
{
	memset(prime,false,sizeof(prime));
	prime[1] = true;
	int i,j;
	for(i=2;i<N;i++)
	{
		if (!prime[i])
			for(j=i*i;j<N;j+=i)
				prime[j] = true;
	}
}

int main()
{
	int t,n,m,i,j,k;
	Prim();
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		k = j =2;
		memset(cnt,0,sizeof(cnt));
		while(k<=n)//分解阶乘n!,逐次分解每个数
		{
			j = k;
			i = 2;
			while(j!=1)	//j==1表示分解完毕
			{
				while(j%i==0)
				{
					j=j/i;
					cnt[i]++;
				}
				for(i++;i<N;i++)	//计算出下一个素数
					if (!prime[i])break;
			}
			k++;
		}
		printf("%d\n",cnt[m]);
	}
}











你可能感兴趣的:(nyoj 56/70(阶乘的因式分解))