1 条题解

  • 1
    @ 2025-4-5 20:01:13

    题解

    先通过递推式求得伯努利数,然后用公式并将中间的(n+1)i(n+1) ^ i,变成nin ^ i,后面再加上nkn ^ k,化进去就行了。简而言之就是由数学伯努利公式代入,通分化简就可以。

    标程

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <vector>
    #include <iostream>
    #include <string>
    #include <ctime>
    
    #define LOCAL
    const int MAXN = 20 + 10;
    const double Pi = acos(-1.0);
    using namespace std;
    
    typedef long long ll;
    
    ll gcd(ll a, ll b) {
        return b == 0 ? a : gcd(b, a % b);
    }
    
    struct Num {
        ll a, b; // 分数,b为分母
        Num(ll x = 0, ll y = 0) { a = x; b = y; }
        void update() {
            ll tmp = gcd(a, b);
            a /= tmp;
            b /= tmp;
        }
        Num operator + (const Num &c) {
            ll fz = a * c.b + b * c.a, fm = b * c.b;
            if (fz == 0) return Num(0, 1);
            ll tmp = gcd(fz, fm);
            return Num(fz / tmp, fm / tmp);
        }
    } B[MAXN], A[MAXN];
    
    ll C[MAXN][MAXN];
    
    void init() {
        // 预处理组合数
        int i, j;
        for (i = 0; i < MAXN; i++) C[i][0] = C[i][i] = 1;
        for (i = 2; i < MAXN; i++)
            for (j = 1; j < MAXN; j++) C[i][j] = C[i - 1][j] + C[i - 1][j - 1];
        
        // 预处理伯努利数
        B[0] = Num(1, 1);
        for (i = 1; i < MAXN; i++) {
            Num tmp = Num(0, 1), add;
            for (j = 0; j < i; j++) {
                add = B[j];
                add.a *= C[i + 1][j];
                tmp = tmp + add;
            }
            if (tmp.a) tmp.b *= -(i + 1);
            tmp.update();
            B[i] = tmp;
        }
    }
    
    void work() {
        int n;
        scanf("%d", &n);
        ll M = n + 1, flag = 0, Lcm;
        A[0] = Num(0, 1);
        
        int i;
        for (i = 1; i <= n + 1; i++) {
            if (B[n + 1 - i].a == 0) {
                A[i] = Num(0, 1);
                continue;
            }
            Num tmp = B[n + 1 - i];
            tmp.a *= C[n + 1][i]; // C[n+1][i] = C[n + 1][n + 1 - i]
            tmp.update();
            if (flag == 0) {
                Lcm = flag = tmp.b;
            }
            A[i] = tmp;
        }
        
        A[n] = A[n] + Num(n + 1, 1);
        
        for (i = 2; i <= n + 1; i++) {
            if (A[i].a == 0) continue;
            Lcm = (Lcm * A[i].b) / gcd(Lcm, A[i].b);
        }
        
        if (Lcm < 0) Lcm *= -1;
        M *= Lcm;
        
        printf("%lld", M);
        for (i = n + 1; i >= 0; i--) {
            printf(" %lld", A[i].a * Lcm / A[i].b);
        }
    }
    
    int main() {
        init();
        work();
        return 0;
    }
    
    
    • 1

    信息

    ID
    708
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者