【bzoj3516】3516: 国王奇遇记加强版(递推)

传送门

题意:
\(\displaystyle \sum_{i=1}^n i^mm^i,n\leq 10^9,m\leq 1000\)

思路:
\(m\)比较小,考虑从\(m\)入手进行递推:

\(f(j)=\sum_{i=1}^ni^jm^i\),则\(mf(j)=\sum_{i=1}^ni^jm^{i+1}\)

接下来就是推式子时间:

\[\begin{aligned} (1-m)f(j)=&\sum_{i=1}^ni^jm^i-\sum_{i=1}^ni^jm^{i+1}\\ =&\sum_{i=0}^{n-1}(i+1)^jm^{i+1}-\sum_{i=0}^{n-1}i^jm^{i+1}-n^jm^{n+1}\\ =&\sum_{i=0}^{n-1}((i+1)^j-i^j)m^{i+1}-n^jm^{n+1}\\ =&\sum_{i=0}^{n-1}(\sum_{k=0}^j{j\choose k}i^k-i^j)m^{i+1}-n^jm^{n+1}\\ =&\sum_{i=0}^{n-1}\sum_{k=0}^{j-1}{j\choose k}i^km^{i+1}-n^jm^{n+1}\\ =&\sum_{k=0}^{j-1}{j\choose k}\sum_{i=0}^{n-1}i^km^{i+1}-n^jm^{n+1}\\ =&\sum_{k=0}^{j-1}{j\choose k}m\sum_{i=0}^{n-1}i^km^{i}-n^jm^{n+1}\\ =&\sum_{k=0}^{j-1}{j\choose k}m(\sum_{i=1}^ni^km^i+(k==0)-n^km^n)-n^jm^{n+1}\\ =&\sum_{k=0}^{j-1}{j\choose k}m(f(k)+(k==0)-n^km^n)-n^jm^{n+1}\\ \end{aligned} \]

式子中需要注意的一点就是,当\(k=i=0\)时,有\(0^0=1\),这是定义,所以我们要特判一下然后加上一个\(1\)
其它就没什么好说的了。感觉这种递推构造两个式子相减还是挺常见的。(就是想不到)
代码如下:

/*
 * Author:  heyuhhh
 * Created Time:  2020/4/17 19:45:42
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1000 + 5, MOD = 1e9 + 7;

int qpow(ll a, ll b) {
    ll res = 1;
    while(b) {
        if(b & 1) res = res * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }   
    return res;
}

int n, m;
int f[N], C[N][N];
int pown[N];

void run() {
    cin >> n >> m;
    if(m == 1) {
        cout << 1ll * n * (n + 1) / 2 % MOD << '\n';
        return;
    }
    pown[0] = 1;
    for(int i = 1; i <= m; i++) pown[i] = 1ll * pown[i - 1] * n % MOD;
    int powm = qpow(m, n), powm1 = qpow(m, n + 1);
    int inv = qpow(1 - m + MOD, MOD - 2);
    f[0] = 1ll * m * (1 - powm + MOD) % MOD * inv % MOD;
    for(int i = 0; i < N; i++) {
        C[i][0] = 1;
        for(int j = 1; j <= i; j++) {
            C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;   
        }
    }
    for(int i = 1; i <= m; i++) {
        f[i] = (MOD - 1ll * pown[i] * powm1 % MOD) % MOD;  
        for(int k = 0; k < i; k++) {
            int res = 1ll * C[i][k] * m % MOD * ((f[k] + (k == 0) - 1ll * powm * pown[k] % MOD + MOD) % MOD) % MOD;
            f[i] = (f[i] + res) % MOD;
        }
        f[i] = 1ll * f[i] * inv % MOD;
    }
    cout << f[m] << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/heyuhhh/p/12742263.html