IT民工
加油!

数论的题做的很少,这道题本来不难,结果在五个小时内还是没做出来。所有a[i]分解质因子,并累计0到100中所有质因子出现的次数存入num数组中。X!要能被M整除,那么在M中出现的所有的质因子就应该在x!中出现并且出现的次数不少于在M中出现的次数。然后二分答案。

有一个计算公式:

LL cal(LL i, LL x)

{

    LL ret = 0;

    while(x)

    {

        x /= i;

        ret += x;

    }

    return ret;

}

可以求出i在X!中出现的次数。

/*Accepted    3641    0MS    252K    1461 B    C++    Yu*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;

typedef __int64 LL;
const int MAXN = 105;
LL a, b, ans;
LL num[MAXN];
int n;
void pre(LL a, LL b)
{
    int i, cnt;
    for(i = 2; i * i <= a; i ++)
    {
        cnt = 0;
        while(a % i == 0)
        {
            a /= i;
            cnt ++;
        }
        num[i] += cnt * b;
        if(a == 1) break;
    }
    if(a > 1) num[a] += b; //此时,a是素数
}

LL cal(LL i, LL x)
{
    LL ret = 0;
    while(x)
    {
        x /= i;
        ret += x;
    }
    return ret;
}

bool judge(LL x)
{
    int i;
    for(i = 1; i <= 100; i ++)
    {
        if(num[i])
        {
            LL t = cal(i, x);
            if(t < num[i])
                return false;
        }
    }
    return true;
}

int main()
{
    int T, i;
    scanf("%d", &T);
    while(T --)
    {
        scanf("%d", &n);
        memset(num, 0, sizeof num);
        for(i = 0; i < n; i ++)
        {
            scanf("%I64d%I64d", &a, &b);
            pre(a, b);
        }
        LL left = 0, right = (LL(1)) << 60;
        while(left <= right)
        {
            LL mid = (left + right) >> 1;
            if(judge(mid))
            {
                ans = mid;
                right = mid - 1;
            }
            else left = mid + 1;
        }
        printf("%I64d\n", ans);
    }
    return 0;
}

 

 

posted on 2012-09-05 16:13  找回失去的  阅读(236)  评论(0)    收藏  举报