Problem 1753 Another Easy Problem
Accept: 326 Submit: 1522
Accept: 326 Submit: 1522
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
3
100 1
50 1
60 1
Sample Output
10
Source
FZU 2009 Summer Training IV--Number Theory
题目大意:求T个组合数的最大公约数。
解题思路:每个数可以表示为素因子的幂的乘积的形式,那么如果一个数比较大不能直接记录,那么就记录它的素因子及每个素因子的个数就可以了,即使这样直接求组合数的素因子及其个数还是有困难,这里用到一个方法,c(n,m)=n!/(m!*(n-m)!),那么c(n,m)的素因子及其个数就等于n!的素因子的个数减去m!的素因子的个数再减去(n-m)!的素因子个数,求n!的素因子p的个数的方法是:
k=n,ans=0;
while(k)
ans+=k/p,k/=p;
每个素因子小于等于n,这样就可以较方便快捷的将组合数用素因子来表示了。
既然已经将组合数用素因子表示了,那么不断更新缩小素因子个数就能求出最大公约数了。
这里有个优化:素因子只用找到T个n中最小的n值就可以,因为再大的也没用,会被最小的n删掉的。
结果记得用long long!!!!
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 100001
bool isnotp[N];
int p[N],num[N],t[N];
int n[105],m[105];
int cnt=0,T,minn;
void makeplist()
{
memset(isnotp,0,sizeof(isnotp));
isnotp[1]=1;
p[cnt++]=2;
int i,j;
for(i=4;i<N;i+=2)
isnotp[i]=1;
for(i=3;i<N;i+=2)
{
if(!isnotp[i])
p[cnt++]=i;
for(j=0;j<cnt&&i*p[j]<N;++j)
{
isnotp[i*p[j]]=1;
if(i%p[j]==0)
break;
}
}
// cout<<"makeplist end"<<endl;
// for(i=0;i<cnt&&p[i]<=100;++i)
// printf("%d ",p[i]);
// printf("\n");
}
void work()
{
memset(num,-1,sizeof(num));
int i,j,k,cas=0;
long long ans=1;
for(i=0;i<T;++i)
{
cas++;
memset(t,0,sizeof(t));
for(j=0;j<cnt&&p[j]<=minn;++j)
{
k=n[i];
while(k>0)
{
t[p[j]]+=k/p[j];
k/=p[j];
}
}
// printf("%d-1 end\n",cas);
// for(j=1;j<=minn;++j)
// if(t[j])
// cout<<t[j]<<" ";
// cout<<endl;
for(j=0;j<cnt&&p[j]<=minn;++j)
{
k=m[i];
while(k)
{
t[p[j]]-=k/p[j];
k/=p[j];
}
}
// printf("%d-2 end\n",cas);
// for(j=1;j<minn;++j)
// if(t[j])
// cout<<t[j]<<" ";
// cout<<endl;
for(j=0;j<cnt&&p[j]<=minn;++j)
{
k=n[i]-m[i];
while(k)
{
t[p[j]]-=k/p[j];
k/=p[j];
}
}
// printf("%d-3 end\n",cas);
// for(j=1;j<minn;++j)
// if(t[j])
// cout<<t[j]<<" ";
// cout<<endl;
for(j=0;j<cnt&&p[j]<=minn;++j)
{
if(num[p[j]]==-1)
num[p[j]]=t[p[j]];
else if(t[p[j]]<num[p[j]])
num[p[j]]=t[p[j]];
}
// printf("%d-4 end\n",cas);
}
for(j=0;j<cnt&&p[j]<=minn;++j)
{
k=num[p[j]];
while(k>0)
ans*=p[j],k--;
}
printf("%I64d\n",ans);
}
int main()
{
int i;
makeplist();
while(scanf("%d",&T)!=EOF)
{
minn=N;
for(i=0;i<T;++i)
{
scanf("%d %d",n+i,m+i);
if(n[i]<minn)
minn=n[i];
}
work();
}
return 0;
}
#include<cstdio>
#include<cstring>
using namespace std;
#define N 100001
bool isnotp[N];
int p[N],num[N],t[N];
int n[105],m[105];
int cnt=0,T,minn;
void makeplist()
{
memset(isnotp,0,sizeof(isnotp));
isnotp[1]=1;
p[cnt++]=2;
int i,j;
for(i=4;i<N;i+=2)
isnotp[i]=1;
for(i=3;i<N;i+=2)
{
if(!isnotp[i])
p[cnt++]=i;
for(j=0;j<cnt&&i*p[j]<N;++j)
{
isnotp[i*p[j]]=1;
if(i%p[j]==0)
break;
}
}
// cout<<"makeplist end"<<endl;
// for(i=0;i<cnt&&p[i]<=100;++i)
// printf("%d ",p[i]);
// printf("\n");
}
void work()
{
memset(num,-1,sizeof(num));
int i,j,k,cas=0;
long long ans=1;
for(i=0;i<T;++i)
{
cas++;
memset(t,0,sizeof(t));
for(j=0;j<cnt&&p[j]<=minn;++j)
{
k=n[i];
while(k>0)
{
t[p[j]]+=k/p[j];
k/=p[j];
}
}
// printf("%d-1 end\n",cas);
// for(j=1;j<=minn;++j)
// if(t[j])
// cout<<t[j]<<" ";
// cout<<endl;
for(j=0;j<cnt&&p[j]<=minn;++j)
{
k=m[i];
while(k)
{
t[p[j]]-=k/p[j];
k/=p[j];
}
}
// printf("%d-2 end\n",cas);
// for(j=1;j<minn;++j)
// if(t[j])
// cout<<t[j]<<" ";
// cout<<endl;
for(j=0;j<cnt&&p[j]<=minn;++j)
{
k=n[i]-m[i];
while(k)
{
t[p[j]]-=k/p[j];
k/=p[j];
}
}
// printf("%d-3 end\n",cas);
// for(j=1;j<minn;++j)
// if(t[j])
// cout<<t[j]<<" ";
// cout<<endl;
for(j=0;j<cnt&&p[j]<=minn;++j)
{
if(num[p[j]]==-1)
num[p[j]]=t[p[j]];
else if(t[p[j]]<num[p[j]])
num[p[j]]=t[p[j]];
}
// printf("%d-4 end\n",cas);
}
for(j=0;j<cnt&&p[j]<=minn;++j)
{
k=num[p[j]];
while(k>0)
ans*=p[j],k--;
}
printf("%I64d\n",ans);
}
int main()
{
int i;
makeplist();
while(scanf("%d",&T)!=EOF)
{
minn=N;
for(i=0;i<T;++i)
{
scanf("%d %d",n+i,m+i);
if(n[i]<minn)
minn=n[i];
}
work();
}
return 0;
}