题意:有N个ai,bi,M=a1^b1*a2^b2*a3^b3…*an^bn ,求最小的 x 使得 x! % M ==0.
思路:把M分成多个素数相乘,num[i] 记录素数 i 的个数,然后二分找到x,若 x! 中所有 i 的个数满足>=num[i]
即为答案。
#include<cstdio> #include<stdlib.h> #include<string.h> #include<string> #include<map> #include<cmath> #include<iostream> #include <queue> #include <stack> #include<algorithm> #include<set> using namespace std; #define INF 1e8 #define eps 1e-8 #define LL long long #define maxn 100105 #define mod 1000000009 int prime[25]={2,3,5,7,11,13,17,19,23,29,31, 37,41,43,47,53,59,61,67,71,73,79,83,89,97}; __int64 num[105]; void Cal(__int64 a,__int64 b)//计算素数i的个数num[i] { for(int i=0;i<25;i++) { while(a%prime[i]==0) { a/=prime[i]; num[prime[i]]+=b; } } } __int64 find(int i,__int64 x)//计算x!中i的个数 { __int64 ans=0; while(x) { x/=i; ans+=x; } return ans; } bool ok(__int64 x) { for(int i=0;i<25;i++) { if(num[prime[i]]) { __int64 tmp=find(prime[i],x); if(tmp<num[prime[i]]) return false; } } return true; } int n; int main() { int t; scanf("%d",&t); while(t--) { __int64 a,b; scanf("%d",&n); memset(num,0,sizeof(num)); for(int i=0;i<n;i++) { scanf("%I64d%I64d",&a,&b); Cal(a,b); } __int64 l=0,r=(__int64)1<<62,mid,ans; while(l<=r) { mid=(l+r)>>1; if(ok(mid)) { ans=mid; r=mid-1; } else l=mid+1; } printf("%I64d\n",ans); } return 0; }
HDU 3641 Treasure Hunting (素数拆分)
时间: 2024-11-06 19:26:10