B 阶乘

最大质因数补丁版

#include <bits/stdc++.h>
using namespace std;
int main() {
    int T;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;
        int ans = -1;
        for (int i = 2; i * i <= n; ++i)
            if (n % i == 0) {
                int cnt = 0;
                while (n % i == 0) {
                    n /= i;
                    ++cnt;
                }
                int j = i;
                for (int tmp = 0;tmp<cnt; j += i)
                    for (int k = j; k % i == 0; k /= i) ++tmp;
                ans = max(ans, j-i);
            }
        cout << max(ans, n) << endl;
    }
    return 0;
}

分解质因数+二分+比对每个质数个数

#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn = 1005;
ll prime_num[maxn], num;  //质因数的个数
ll prime[maxn];
const ll mod = 1e9 + 7;
void divid(ll n)  //分解正整数n
{
    num = 0;
    if (n % 2 == 0) {
        ll term = 0;
        while (n % 2 == 0) {
            term++;
            n /= 2;
        }
        prime_num[num] = term;
        prime[num++] = 2;
    }
    for (ll i = 3; i * i <= n; i += 2)
        if (n % i == 0) {
            ll 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;
    }
}
//假设s为n!的一个质因数,k=n/s,m为不能被s整除的数;则(1s*2s*....*ks)*m=n!-->s^k*k!*m=n!如此递归可求出s^r*m=n!的形式
// s为n!的一个质因数,x为n!中质因数s的个数则x=n/s+n/p^s+...;
ll factory(ll n, ll s)  //求n!中质数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() {  //求π(pow(pi,n!/pi)) ,pi为x的质因数
    int t;
    scanf("%d", &t);
    while (t--) {
        ll x;
        scanf("%lld", &x);
        if (x <= 5) {
            printf("%lld\n", x);
            continue;
        }
        divid(x);
        ll left = 1, right = x, ans = x;
        while (left <= right) {
            ll mid = (left + right) / 2;
            if (check(mid)) {  //搜索尽可能小的
                ans = mid;
                right = mid - 1;
            } else
                left = mid + 1;
        }
        printf("%lld\n", ans);
    }
    return 0;
}

核心在

//假设s为n!的一个质因数,k=n/s,m为不能被s整除的数;则(1s*2s*....*ks)*m=n!-->s^k*k!*m=n!如此递归可求出s^r*m=n!的形式
// s为n!的一个质因数,x为n!中质因数s的个数则x=n/s+n/p^s+...;
ll factory(ll n, ll s)  //求n!中质数s的个数的函数
{
    ll sum = 0;
    while (n) {
        n /= s;
        sum += n;
    }
    return sum;
}

https://blog.csdn.net/nameofcsdn/article/details/52232438

多个连续素数的和表示正整数

POJ 2739 Sum of Consecutive Prime Numbers
http://poj.org/problem?id=2739
翻译https://blog.csdn.net/woniupengpeng/article/details/53696743

#include <iostream>
#define sscc ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const int N=2000,n=10000;
int prime[N],total=0;
bool chk(int k) {
    for(int i=0; i<total; i++)
        if(k%prime[i]==0)
            return false;
    return true;
}
void pre() {
    for(int i=2; i<n; i++)
        if(chk(i))
            prime[total++]=i;
    prime[total]=n+1;
}
int main() {
    pre();
    int m;
    while(cin>>m,m) {
        int ans=0;
        for(int i=0; prime[i]<=m; i++) {
            int cnt=0;
            for(int j=i; j<total,cnt<m; j++)
                cnt+=prime[j];
            if(cnt==m)
                ++ans;
        }
        cout<<ans<<endl;
    }
    //cout<<"0";
    return 0;
}

求1--r中与n互素数的个数

容斥原理的应用,具体分析见下面代码注释:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n, r;

//计算1--r中与n互素数的个数
//思路跟计算n的欧拉函数值一样,但这里没有公式化简
//所以采用k位2进制进行模拟(k表示n在r范围内素因子的个数)
//从1--2^k-1中的每一位数的二进制中1的分布表示刚好可以对应
//不同的因子组合情况
int solve() {
    int i, j, k = 0, ans = 0;
    int prime[100];  // n的素因子表
    for (i = 2; i * i <= n; i++)  //求出1--r中n所有的素因子,控制条件必须是i*i,否则会超时
        if (n % i == 0) {
            prime[k++] = i;
            while (n % i == 0) n = n / i;
        }
    if (n > 1)  //除了最后n未除尽的情况外,i=2,3或n为素数的情况也都由此处理
        prime[k++] = n;
    for (i = 1; i < (1 << k); i++)  // i<<N表示2^N
    {
        j = i;
        int cnt = 0, mult = 1;  // mult用于记录每一种情况下因子的最小公倍数
        int m = 0;  // m用于记录二进制的位数
        while (j) {
            if (j & 1) {
                cnt++;  //记录二进制中1的个数,即因子的个数
                mult = mult * prime[m];
            }
            j = j >> 1;  // j右移一位
            m++;
        }
        int cur = r / mult;  // 1--r中能被mult整除数的个数
        if (cnt % 2)         //奇数个因子情况
            ans += cur;
        else
            ans -= cur;
    }
    return r - ans;
}

int main() {
    while (cin >> r >> n) {
        int n1 = n;
        int ans = solve();
        cout << "1--" << r << "中与" << n1 << "互素数的个数为: " << ans << endl;
    }
    return 0;
}

原文链接:https: // blog.csdn.net/acm_lkl/article/details/38520619

求一个数的所有因数+质因数分解【数论】
https://blog.csdn.net/Z_sea/article/details/82118417