题目链接:HDU 3641 Treasure Hunting
题意:求X!%M==0中最小的的X。其中M=a1^b1*a2^b2*a3^b3....
思路:求余为0想到整除,即分母的因子构成的集合是分子的因子构成的集合的子集。因子又想到,任何一个整数都可以分解成若干个素数相乘。
注意:题目数据很大,查到答案时二分。
AC代码:
#include<stdio.h>
#include<string.h>
#define ll __int64
bool Prime[210];
ll num[210];//M中的质因数个数
void getPrime()//素数打表
{
int i,j;
memset(Prime,true,sizeof Prime);
Prime[0]=Prime[1]=false;
for(i=2;i*i<=110;i++)
{
if(Prime[i])
{
for(j=i+i;j<=110;j+=i)
Prime[j]=false;
}
}
}
void cal(ll a,ll b)//分解质因子
{
ll i,n=a;
for(i=2;i<=a;)
{
if(n%i==0 && Prime[i])
{
n/=i;
num[i]+=b;
}
else
i++;
}
}
ll find(ll i,ll x) //x!中i的个数
{
ll ans=0;
while(x)
{
x/=i;
ans+=x;
}
return ans;
}
bool ok(ll x)//
{
ll i;
for(i=1;i<=100;i++)
{
if(num[i])
{
ll temp=find(i,x);
if(num[i]>temp) //分母的质因子个数比分子质因子大。
return false;
}
}
return true;
}
ll bfind()//二分查到答案
{
ll ans=0;
ll left,right,mid;
left=0;
right=ll(1)<<62;
while(left<=right)
{
mid=(left+right)>>1;
if(ok(mid))
{
ans=mid;//为了得到最小。
right=mid-1;
}
else
left=mid+1;
}
return ans;
}
int main()
{
int t,n,i;
ll a,b;
getPrime();
while(scanf("%d",&t)!=EOF)
{
while(t--)
{
memset(num,0,sizeof num);
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%I64d %I64d",&a,&b);
cal(a,b);
}
ll ans=0;
ans=bfind();
printf("%I64d\n",ans);
}
}
return 0;
}