您的位置:首页 > 其它

Ural1055(素数打表+分解质因数)

2014-10-17 09:22 232 查看

1055. Combinations

Time limit: 1.0 second

Memory limit: 64 MB

Background

As you have known MMM corporation lab researches the matter of haricot proportions in soup For every day. As we wrote in the previous problem (T) the ladle is placed down into the soup pan. But now we are not interested in the
form and linear sizes of the ladle. This time the ladle holds exactly M haricot seeds of
N got into the pan. All the seeds are of different size.

Experimenters calculate the quantity of possible methods to proportion
M seeds in the pan. Requisite quantity of methods is calculated with the formula:
C = N!/(M!·(N−M)!). The main feature of these experiments is the quantity of different prime divisors of number
C.

Example. N = 7, M = 3. C = 7!/(3!*4!) = 5040/(6*24) = 35 = 5*7. This example shows that the quantity of different prime divisors is 2.

Lest money would be spent for programmer, MMM corporation board decided to make necessary estimating during trial tour of quarterfinal world programming contest in Rybinsk.

Problem

Thus, your aim is to find the quantity of different prime divisors of number
C.

Input

Input contains integers N and M.You may assume that 1 ≤ M < N ≤ 50000.

Output

Output should contain one integer.

Sample

inputoutput
7 3

2

Problem Source: Rybinsk State Avia Academy
题意就是要求 C = N!/(M!·(N−M)!)的值的因子的种类,但是阶乘数据太大,不可能直接求。然后就利用分解质因数的办法,把分子和分母都分解质因数,然后因子的个数再相减,然后统计剩下的因子的个数就可以了。
首先素数打表:
这里直接套用的模板,有些东西是不必要的,刚开始直接利用的isPrime[i]判断是不是素数,然后再判断是不是因子,果断TLE。。~~~~(>_<)~~~~ ,后来才发现别人是直接拿素数试的。。。。:-(。。。。笨的无可救药啊
另外这里补充一些素数打表的基础知识。
原理:

1. 任何一个合数都可以表示成一个质数和一个数的乘积

2. 假设A是一个合数,且A = x * y,这里x也是一个合数,那么有:

A = x * y; (假设y质数,x合数)

x = a * b; (假设a是质数,且a < x)

-> A = a * b * y = a * Z (Z = b * y)

即一个合数(x)与一个质数(y)的乘积可以表示成一个更大的合数(Z)与一个更小的质数(a)的乘积

这也是理解代码中 if(i%primes[j] == 0)break;的关键

例如: 如果i = 8; 那么由于i%2 == 0; 因此对于i=8就只需要检查primes[1]即可,因为对于大于primes[1]的质数,像3,有:

8*3 = 2*4*3 = 12*2

也就是说24(8*3=24)并不需要在8时检查,在12时才检查

其他的都好说辣,s1[i]表示质因子为i的个数,val=1,就表示是分子,个数加上1就好,val=-1,表示是分母,个数减去1就好。最后统计s1[]中非零的个数就是答案辣~~

//先计算阶乘,然后分解质因子   阶乘数据量太大,会爆栈 。。。 
//将组合数依次分解因子,然后记录因子的总个数,最后除数与被除数想减就可以辣。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
#define maxn 50055
#define ll long long 
bool isPrime[maxn];
int prime[maxn];
int s1[maxn];
int total;

void makePrime()  
{  
    memset(isPrime, true, sizeof(isPrime));  
    memset(prime, 0, sizeof(prime));  
    int i, j;  
    for (i=2; i<maxn; i++)  
    {  
        if (isPrime[i]) prime[total++] = i;  
        for (j=0; j<total && i*prime[j]<maxn; j++)  
        {  
            isPrime[i*prime[j]] = false;  
            if (i%prime[j]==0) break;  
        }  
    }  
}  
  

void dis(int n,int val)
{
	int i,count=0;
	for(i=0;prime[i]<=n;)
	{
		count=0;
		if(n%prime[i]==0 && n>1)
	    {
	       count++;
		   n/=prime[i]; 
		}
		else i++;
		
		s1[prime[i]]+=(count*val);		
	}
}

int main()
{
	int m,n,i;
	total=0;
    makePrime();
   
	scanf("%d%d",&n,&m);

	
	for(i=n;i;i--)
		dis(i,1);
	for(i=m;i;i--)
		dis(i,-1);
	for(i=n-m;i;i--)
	    dis(i,-1);
	
   int res=0;
   for(i=2;i<=n;i++)
   	   if(s1[i]!=0)res++;
   
	cout<<res<<endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: