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;
}