题目链接: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; }
HDU 3641 Treasure Hunting (二分+分解质因子)
时间: 2024-10-11 23:28:10