阶乘

阶乘

https://ac.nowcoder.com/acm/contest/5505/C

Solution

题面简洁明了,(就喜欢这种题面)。首先我们需要知道的前导知识,任何一个数,都可以分解为一些素数的幂之积,又叫唯一分解定理,那么对于阶乘这样一个乘积运算,自然也可以进行多次分解质因数。写成素数幂之积。这里给出阶乘求解质因数幂的算法

ll factory(ll n, ll s) { //n!对素数s的求解
    ll sum = 0;
    while (n) {
        n /= s;
        sum += n;
    }
    return sum;  //返回幂
}

那么知道了分解质因数之后,首先如果当前答案的阶乘是p的倍数,就说明每一个素数幂大于等于p的对应素数幂,并且这个答案我们希望再小一点,如果当前答案阶乘不是p的倍数,就说明存在一个素数的幂小于p对应素数幂,并且这个答案一定要比求解答案小。符合单调,选择二分。

知道这样两个知识之后这题也就解决了,只存在把这些函数接口接好。
1、对p分解质因数求解到对应素数与对应幂
2、二分答案,对答案也分解质因数,与p的幂对比

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1000;

ll prime_num[maxn], num;//质因数的个数
ll prime[maxn];

void divid(ll n) {
    num = 0;
    ll i, term;
    for (int i = 2; i * i <= n; ++i)
        if (n % i == 0) {
            term = 0;
            while (n % i == 0) {
                ++term;
                n /= i;
            }
            prime_num[num] = term;
            prime[num++] = i;
        }
    if (n > 1) {
        prime[num] = n;
        prime_num[num++] = 1;
    }
}

ll factory(ll n, ll s) {
    ll sum = 0;
    while (n) {
        n /= s;
        sum += n;
    }
    return sum;
}

bool check(ll x) {
    for (int i = 0; i < num; ++i)
        if (factory(x, prime[i]) < prime_num[i])    return false;
    return true;
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        ll x;
        scanf("%lld", &x);
        if (x <= 2) {
            printf("%lld\n", x);
            continue;
        }
        divid(x);
        ll l = 1, r = 1e16, ans;
        while (l <= r) {
            ll mid = l + ((r - l) >> 1);
            if (check(mid)) {
                ans = mid;
                r = mid - 1;
            }
            else    l = mid + 1;
        }
        printf("%lld\n", ans);
    }
    return 0;
}

!!这里突然发现个更短时间的代码,上面代码跑了457MS,下面跑了144MS。想想也是,毕竟没有二分,掉了这里log的复杂度把,这里说一句不愧是杨大佬,不愧是这次周练第二的男人,tql!!直接跑质因数的幂结果大于等于p的当前素数幂,并计算符合要求的最小次幂的计算结果,并把答案更新。

#include<bits/stdc++.h>
#define  js  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
int main() {
    int t,n,i,j,ans=0;
    js;
    cin>>t;
    while(t--) {
        cin>>n;
        ans=0;
        for(i=2;i*i<=n;++i) if(n%i==0) { //i是n的一个因子
            int cnt=0;
            while(n%i==0) { //计算i的幂
                n/=i;
                ++cnt;
            }
            int tmp=0;
            for(j=i;;j+=i) { //找到符合要求的j的最小倍数
                for(int p=j;p%i==0;p/=i,++tmp);
                if(tmp>=cnt) break;
            }
            ans=max(ans,j);
        }
        cout<<max(ans,n)<<endl;
    }
}
全部评论

相关推荐

10-24 13:36
门头沟学院 Java
Zzzzoooo:更新:今天下午有hr联系我去不去客户端,拒了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务