HDU 3641 Treasure Hunting(阶乘素因子分解+二分)
题目链接:传送门
题意:
求最小的 ( x! ) = 0 mod (a1^b1*a2^b2...an^bn)
分析:
首先吧a1~an进行素因子分解,然后统计下每一个质因子的指数。因为随着x的增大,质因子的个数是逐渐添加的
因此我们能够二分x。对x!进行素因子分解推断是否满足条件。然后求出最小的就能够了。
代码例如以下:
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; const int maxn = 110; typedef long long LL; bool vis[maxn]; int p[maxn],cnt; LL a[maxn]; LL b[maxn]; LL num[maxn]; void init(){ cnt = 0; memset(vis,0,sizeof(vis)); for(int i=2;i<maxn;i++){ if(!vis[i]){ p[cnt++]=i; for(int j=i+i;j<maxn;j+=i) vis[j]=1; } } } LL get_num(LL x,int pri){ if(x<pri) return 0; return get_num(x/pri,pri)+(LL)x/pri; } bool check(LL x){ for(int i=0;i<cnt;i++){ if(get_num(x,p[i])<num[p[i]]) return false; } return true; } int main() { init(); int t,n; scanf("%d",&t); while(t--){ scanf("%d",&n); memset(num,0,sizeof(num)); for(int i=0;i<n;i++){ scanf("%I64d%I64d",a+i,b+i); int tmp = a[i]; for(int j=0;p[j]*p[j]<=tmp&&j<cnt;j++){ if(tmp%p[j]==0){ LL tot=0; while(tmp%p[j]==0) tmp=tmp/p[j],tot++; num[p[j]]+=tot*b[i]; } } if(tmp>1) num[tmp]+=b[i]; } LL ans = 0; for(int i=0;i<maxn;i++) ans=max(ans,(LL)i*num[i]); LL l=0,r=ans; while(l<=r){ LL mid=(l+r)>>1; if(check(mid)) r=mid-1; else l=mid+1; } printf("%I64d\n",l); } return 0; } /* 111 6 6 1000000000000 15 1000000000000 13 1000000000000 7 1000000000000 2 1000000000000 3 1000000000000 */