hdu 3641 神二分 有木有

题意,告诉你一个数m,求最小的x!满足x!%m== 0;

解:

       将m的所有质数因子和质数因子的个数存起来。二分x,对于每个m的质因子p,x!的p的个数都大于等于m的质因子个数就行了。对于二分的上限还是得注意的。就因为这个wa了一个。二分的下限也得注意,从0开始。

      二分真是好神!记得对于大数要写LL。

/*
Pro: 0

Sol:

date:
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#define inf 99999999999999999999LL
using namespace std;
int prime[30],sub;
__int64 num[110];
void getprime(){
    bool flag[111] ;    sub = 0;
    memset(flag , true, sizeof(flag));
    for(int i = 2; i <= 110; i ++)
        for(int j = i + i; j <= 110;j += i)
            flag[j] = false;

    for(int i = 2; i <= 100; i ++)
        if(flag[i]) prime[sub ++] = i;
}
__int64 getnum(__int64 x, int p){//
    __int64 sum = 0;
    while(x % p == 0){
        sum ++;
        x /= p;
    }return sum;
}
bool can(__int64 indx){
    for(int i = 0; i < sub; i ++){
//        printf("%d   %d\n",i,prime[i]); 我还以为又是数组越界的奇怪问题呢,原来是这个函数被多次调用
        if(prime[i] && num[prime[i]]){
            __int64 sum = 0;
            for(__int64 k = prime[i]; k <= indx; k *= prime[i])
                sum += indx / k;
            if(sum < num[prime[i]]) return false;
        }
    }
    return true;
}
__int64 bin(){
    __int64 low = 0, high = inf, mid ;
    while(low <= high){
        mid = (low + high) >> 1;
//         printf("%d&&\n",mid);
        if(can(mid))    high = mid - 1;
        else low = mid + 1;
    }
    return low;
}
int main(){
    getprime();
//    __int64 kk = 10000000000000 * 100;  __int64 sum = 0;
//                  99999999999999999999
//    __int64 in  = 33333333333333333333;
//    for(__int64 ka = 97; ka <= in; ka *= 97)
//        sum += in / ka;
//    if(sum >= kk) puts("yes");
//    else puts("no");

    int t,n,a;  __int64 b;
    scanf("%d",&t);
    while(t -- ){
        scanf("%d",&n);
        memset(num,0,sizeof(num));
        for(int i = 0; i < n; i ++){
            scanf("%d%I64d",&a,&b);
            for(int j = 0; j < sub; j ++){
                if(a % prime[j] == 0){
                    num[prime[j]] += getnum(a,prime[j]) * b;
                }
            }
        }
        printf("%I64d\n",bin());
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值