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

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!·( NM)!). 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!·(NM)!)的值的因子的种类,但是阶乘数据太大,不可能直接求。然后就利用分解质因数的办法,把分子和分母都分解质因数,然后因子的个数再相减,然后统计剩下的因子的个数就可以了。
首先素数打表:
 这里直接套用的模板,有些东西是不必要的,刚开始直接利用的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;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值