FZU 1753:Another Easy Problem _素因子分解

Problem 1753 Another Easy Problem

Accept: 268    Submit: 1302
Time Limit: 1000 mSec    Memory Limit : 32768 KB

Problem Description

小TT最近学习了高斯消元法解方程组,现在他的问题来了,如果是以下的方程,那么应该如何解呢?

C(n1,m1)==0 (mod M)

C(n2,m2)==0 (mod M)

C(n3,m3)==0 (mod M)

................

C(nk,mk)==0 (mod M)

小TT希望你告诉他满足条件的最大的M

其中C(i,j)表示组合数,例如C(5,2)=10,C(4,2)=6...

Input

输入数据包括多组,每组数据的第一行是一个正整数T(1<=T<=150)表示接下来描述的T个方程

接下来T行,每行包括2个正整数ni,mi (1<=mi<=ni<=100000)

Output

输出一行答案,表示满足方程组的最大M。

Sample Input

3100 150 160 1

Sample Output

10

Source

FZU 2009 Summer Training IV--Number Theory


//其实题意就是求n个组合数的最大公约数! 对每个组合数素因子分解,然后求求出素因子并集,最后把这些素因子相乘即可!

//本题在一些细节优化上需要做好!自己超时了十余次不断修改优化才AC!


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define min(a,b) (a<b?a:b)
#define LL long long
#define maxn 100005
#define INF 155

struct NODE
{
	int prime,ans;
}node[maxn];
int x[maxn],A[INF],B[INF],m=0,minnum;

void isprime() //筛选出100000以内的素因子
{
	int i,tmp;
	memset(x,0,sizeof(x));
	x[0]=x[1]=1;
	for(i=2;i<maxn;i++)
		if(!x[i])
		{
			node[++m].prime=i;
			tmp=i*2;
			while(tmp<maxn)
				x[tmp]=1,tmp+=i;
		}
}

void make_ans(int n1,int n2,int n3,int d)
{
	int i,tmp,num;
	for(i=1;i<=m&&node[i].prime<=minnum;i++)
	{
		num=0; //注意3:因为只调用一次函数每次针对单个素因子运算,所以不必要用数组记录,只用变量即可!省去了在之前的for循环中每次对数组清零,这也是本题的最大优化之处,之前没多想,一直TLE.
		if(node[i].prime<=n1)
		{
			tmp=n1;
			while(tmp)
				num+=tmp/node[i].prime,tmp/=node[i].prime;
		}
		if(node[i].prime<=n2)
		{
			tmp=n2;
			while(tmp)
				num-=tmp/node[i].prime,tmp/=node[i].prime;
		}
		if(node[i].prime<=n3)
		{
			tmp=n3;
			while(tmp)
				num-=tmp/node[i].prime,tmp/=node[i].prime;
		}
		if(d==1)
			node[i].ans=num;
		else
			node[i].ans=min(node[i].ans,num);
	}
}

int main()
{
	isprime();
	int T,t,i,j;
	while(~scanf("%d",&T))
	{
		for(i=0;i<maxn;i++)
			node[i].ans=0;
		minnum=100001;
		for(t=1;t<=T;t++)
		{
			scanf("%d%d",&A[t],&B[t]);
			if(A[t]<minnum)  //注意1:因为是求组合数的素因子分解并集,显然大于最小的n的素因子不用统计!
				minnum=A[t];
		}
		for(t=1;t<=T;t++)
			make_ans(A[t],B[t],A[t]-B[t],t); //注意2:对C(n,m)素因子分解!n!/(m!*(n-m)!)不需要调用三次函数,直接在函数里面针对某个因子做三次运算,自己之前求C(n,m)都是调用三次函数求n!的素因子分解,在这里就很耗时了!
		LL sum=1;
		for(i=1;i<=m;i++)
			if(node[i].ans)
				for(j=1;j<=node[i].ans;j++)
					sum*=node[i].prime;
		printf("%I64d\n",sum);		
	}
	return 0;
}



你可能感兴趣的:(优化,struct,input,n2,output,Training)