伯努利数记录

1.伯努利数能干啥

伯努利数求自然幂和
i = 1 n i k = 1 k + 1 i = 1 k + 1 ( k + 1 i ) B k + 1 i ( n + 1 ) i \sum_{i=1}^{n} i^k = \frac{1}{k+1}\sum_{i=1}^{k+1}\binom{k+1}{i}B_{k+1-i}(n+1)^i

2.怎么得到啊

1. O ( k 2 ) O(k^2) 递推

B 0 = 1 B_0 = 1

k = 0 n ( n + 1 k ) B k = 0 \sum_{k=0}^{n}\binom{n+1}{k}B_k = 0

B n = 1 n + 1 i = 0 n 1 ( n + 1 i ) B i B_n = -\frac{1}{n+1} \sum_{i=0}^{n-1} \binom{n+1}{i}B_i

题目: 51nod 序列求和V2

code:

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdio>

using namespace std;
typedef long long ll;

const int maxn = 1e5+10;
const int mod = 1e9+7;

ll inv[maxn],fac[maxn],iinv[maxn];
ll B[maxn];

ll qpow(ll a,ll b){
    a %= mod;
    ll ret = 1;
    while(b){
        if(b&1) ret = ret * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ret;
}

ll Inv(ll n){
    return qpow(n,mod-2);
}

void Add(ll& x,ll y){
    x += y;
    if(x>=mod) x -= mod;
}

void Mul(ll& x,ll y){
    x *= y;
    if(x>=mod) x %=mod;
}

inline ll C(int n, int m) {
    return fac[n] * iinv[n - m] % mod*iinv[m] % mod;
}

void init() {
    fac[0] = fac[1] = inv[0] = inv[1] = 1;
    iinv[0] = iinv[1] = 1;
    for(int i = 2; i <maxn; i++) fac[i] = fac[i - 1] * i %mod;
    for(int i = 2; i <maxn; i++) inv[i] = inv[mod % i] * (mod - mod/i) % mod;
    for(int i = 2; i <maxn; i++) iinv[i] = iinv[i-1] * inv[i] % mod;
    B[0] = 1;
    for(int i = 1;i<2005;i++){
        B[i] = 0;
        for(int j = 0;j<i;j++){
            Add(B[i],C(i+1,j) * B[j] % mod); 
        }
        Mul(B[i],inv[i+1]);
        B[i] = -B[i];
        Add(B[i],mod);
    }
}


int main(){
    init();
    int T;
    scanf("%d",&T);
    while(T--){
        ll n,k;
        scanf("%lld%lld",&n,&k);
        ll ans = 0;
        for(int i = 1;i<= k+1;i++){
            ll ret = C(k+1,i);
            Mul(ret,B[k+1-i]);
            Mul(ret,qpow(n+1,i));
            Mul(ret,inv[k+1]);
            Add(ans,ret);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

2.多项式求逆元 O ( n l o g n ) O(nlogn)

G e ( x ) = i = 0 B i i ! x i = x e x 1 = x i = 1 x i i ! = 1 i = 0 x i ( i + 1 ) ! \begin{aligned} G_e(x) &amp;= \sum_{i=0}^{\infty} \frac{B_i}{i!}x^i \\ &amp;= \frac{x}{e^x-1} \\ &amp; = \frac{x}{\sum_{i=1}^{\infty}\frac{x^i}{i!}} \\ &amp; = \frac{1}{\sum_{i=0}^{\infty}\frac{x^i}{(i+1)!}} \end{aligned}

注意求出的 B i B_i 要乘上 i ! i! 才是伯努利数。

题目:51nod 序列求和V4

code:用的是三模数NTT方法处理任意模数。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int maxn = 5e5 + 10 , g = 3;
const int M[] = {998244353,1004535809,469762049};
const ll _M = (ll)M[0] * M[1];
const int mod = 1e9 + 7;
const double eps = 1e-3;

int rev[maxn];
ll fac[maxn],inv[maxn];

ll qmul(ll a, ll b, ll c){
    a %= c;    b %= c;
    ll ret = a * b - (ll)((long double)a * b / c + eps) * c;
    return ret < 0 ? ret + c : ret;
}

inline ll qpow(ll a,ll b,ll P){
    ll ret = 1;
    a %= P;
    for(;b;b>>=1,a=a*a%P) if(b&1) ret = ret * a % P;
    return ret;
}

const int m1 = M[0],m2 = M[1],m3 = M[2];
const int inv1 = qpow(m1 % m2,m2-2,m2);
const int inv2 = qpow(m2 % m1,m1-2,m1);
const int inv12 = qpow(_M % m3,m3-2,m3);

ll CRT(ll a1, ll a2, ll a3){
    ll ret = qmul(a1 * m2 % _M, inv2, _M); 
    (ret += qmul(a2 * m1 % _M, inv1, _M)) %= _M;
    ll ans = ((a3 - ret) % m3 + m3) % m3 * inv12 % m3;
    ans = (ans % mod * (_M % mod) % mod + ret % mod) % mod;
    return ans;
}

inline ll C(int n, int m){
    return fac[n] * inv[n - m] % mod * inv[m] % mod;
}

void init(int n){
    fac[0] = fac[1] = inv[0] = inv[1] = 1;
    for (int i = 2; i <= n; i++) fac[i] = fac[i - 1] * i % mod;
    for (int i = 2; i <= n; i++) inv[i] = inv[mod % i] * (mod - mod / i) % mod;
    for (int i = 2; i <= n; i++) inv[i] = inv[i-1] * inv[i] % mod;
}

struct NTT{
    int P;
    int num,w[2][maxn];
    void Pre(int _P,int m){
        num = m; P = _P;
        int wn = qpow(g,(P-1)/num,P);
        int _wn = qpow(wn,P-2,P);
        w[1][0] = w[0][0] = 1;
        for(int i = 1;i<num;i++) w[1][i] = (ll)w[1][i-1] * wn % P;
        for(int i = 1;i<num;i++) w[0][i] = (ll)w[0][i-1] * _wn % P;
    }
    void DFT(int* a,int N,int r){
        for(int i = 1;i<N;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
        for(int i = 1;i<N;i<<=1)
            for(int j = 0;j<N;j+=(i<<1))
                for(int k = 0;k<i;k++){
                    int x = a[j+k],y = 1LL * a[i+j+k] * w[r][num/(i<<1)*k] % P;
                    a[j+k] = (x+y) % P; a[i+j+k] = (x + P - y) % P;
        }
        if(!r) for(int i = 0,Inv = qpow(N,P-2,P);i<N;i++) a[i] = 1LL * a[i] * Inv % P;
    }
}ntt[3];

int tmp[maxn],_b[3][maxn],c[maxn],a[maxn],b[maxn];

void Get_Inv(int* a,int* b,int n){
    if(n == 1){
        b[0] = qpow(a[0],mod-2,mod);
        return ;
    }
    Get_Inv(a,b,n>>1);
    int L = 0; while(!(n>>L&1)) L++;
    for(int i = 1;i<(n<<1);i++) rev[i] = (rev[i>>1]>>1)|((i&1)<<L);
    for(int k = 0;k<3;k++)
        for(int i = 0;i<n;i++) _b[k][i] = b[i],_b[k][i+n] = 0;
    
    for(int k = 0;k<3;k++){
        for(int i = 0;i<n;i++) tmp[i] = a[i],tmp[i+n] = 0;
        ntt[k].DFT(tmp,n<<1,1); ntt[k].DFT(_b[k],n<<1,1);
        for(int i = 0;i<(n<<1);i++) _b[k][i] = 1LL *_b[k][i] * tmp[i] % ntt[k].P;
        ntt[k].DFT(_b[k],n<<1,0);
    }
    for(int i = 0;i<n;i++) _b[0][i]=_b[1][i]=_b[2][i] = (mod - CRT(_b[0][i],_b[1][i],_b[2][i])) % mod;
    _b[0][0] = _b[1][0] = _b[2][0] = (_b[0][0] + 2) % mod;

    for(int k = 0;k<3;k++){
        for(int i = 0;i<n;i++) tmp[i] = b[i],tmp[i+n] = 0;
        ntt[k].DFT(tmp,n<<1,1); ntt[k].DFT(_b[k],n<<1,1);
        for(int i = 0;i<(n<<1);i++) _b[k][i]=1LL*_b[k][i] * tmp[i] % ntt[k].P;
        ntt[k].DFT(_b[k],n<<1,0);
    }
    for(int i = 0;i<n;i++) b[i] = CRT(_b[0][i],_b[1][i],_b[2][i]);
}

int main(){
    int N = 1;
    for(N = 1;N<=50001;N<<=1);
    init(N+1);
    ntt[0].Pre(m1,N<<1);
    ntt[1].Pre(m2,N<<1);
    ntt[2].Pre(m3,N<<1);
    for(int i = 0;i<N;i++) a[i] = inv[i+1];
    Get_Inv(a,b,N);   
    for(int i = 0;i<N;i++) b[i] = 1LL*b[i] * fac[i] % mod; 
    int T;
    scanf("%d",&T);
    while(T--){
        ll n;
        int k;
        scanf("%lld%d",&n,&k);
        n %= mod;
        ll ans = 0;
        ll p = 1;
        for(int i = 1;i<=k+1;i++){
          p = p * (n+1) % mod;
          ans += C(k+1,i)*b[k+1-i] % mod * p % mod;
          ans %= mod;
        }
        ans = ans * inv[k+1] % mod * fac[k] % mod;
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/oWuHen12/article/details/82877956