hdu 3641 - Treasure Hunting(筛素数+二分)

题意:

求最小的x!使得x!>= a1^b1*a2^b2*a3^b3.......;

思路:

a总是在100以内的,所以分解质因数,保存其各个质因数的个数即可保存下来这个very big的大数;

然后二分x,求解最小的x即可。

代码如下:

typedef long long LL;
typedef unsigned long long LLU;
const int M = 105;

int prime[M];
bool vis[M];

void getprime()
{
    int tot = 0;
    memset(vis,0,sizeof(vis));
    memset(prime,0,sizeof(prime));
    for(int i = 2; i < M; ++i)
    {
        if(!vis[i]) prime[tot++] = i;
        for(int j = 0; j < tot; ++j)
        {
            if(i*prime[j]>=M) break;
            vis[i*prime[j]] = true;
            if(i%prime[j]==0) break;
        }
    }
}
LL cnt[M];
void divide(LL a, LL x)
{
    for(int i = 0; a && prime[i]<=a; ++i)
    {
        if(a%prime[i]==0)
        {
            while(a%prime[i]==0)
            {
                cnt[prime[i]]+=x;
                a/=prime[i];
            }
        }
    }
}
LL getM(LL x, int a)
{
    LL ans = 0;
    while(x)
        ans += (x/=a);
    return ans;
}
bool ok(LL x)
{
    for(int i = 0; prime[i]; ++i)
    {
        LL tmp = getM(x, prime[i]);
        if(tmp<cnt[prime[i]])
            return false;
    }
    return true;
}
int main()
{
    int t, n;
    LL a, b;
    scanf("%d", &t);
    getprime();
    while(t--)
    {
        memset(cnt, 0, sizeof(cnt));
        scanf("%d", &n);
        for(int i = 0; i < n; ++i)
        {
            scanf("%I64d%I64d", &a, &b);
            divide(a,b);
        }
        LL L = 0, R = (1LLU<<63)-1, Mid;
        while(L<R)
        {
            Mid = (R-L)/2+L;
            if(ok(Mid))
                R = Mid;
            else
                L = Mid+1;
        }
        printf("%I64d\n", L);
    }
    return 0;
}


你可能感兴趣的:(hdu 3641 - Treasure Hunting(筛素数+二分))