546 字
3 分钟
Codeforces 622F The Sum of the k-th Powers
题目
题解
设,当k很小的时候,可以找到一些通项公式,比如:当时,,当时,。
可以发现,实际上是一个次多项式函数。
因此,我们就可以使用拉格朗日插值法来推导了。
确定一个k+1次多项式需要k+2个点,我们很容易通过打表得到的值。
然后代入插值公式:
所以
但是这个公式的复杂度时的,我们再优化一下。
设,则
对于,我们将它分成和两部分来考虑,
带入原式,得:
至此,我们可以通过打表的方式,在时间内得到了。
注意
当时,该公式时不适用的,因为会为。
但是我们可以直接通过计算。
代码
/*---------------------------------
@Author: Dicer @DateTime: 2019-06-18 10:16:23
---------------------------------*/
#include <bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<int, int> pii;inline ll qpow(ll a,ll b,ll mod){ll res=1;while(b){if(b&1)res = (res*a)%mod;a=(a*a)%mod;b>>=1;}return res;}const double eps = 1e-8;const int INF = 0x3f3f3f3f;const int mod = 1e9+7;const int MAXN = 1e6 + 7;
ll F[MAXN], fac[MAXN], T;int n, k;
ll inv(ll x){ return qpow(x, mod-2, mod);}void init(){ F[1] = 1; for(int i = 2; i <= k+2; ++i){ F[i] = F[i-1] + qpow(i, k, mod); F[i] %= mod; } fac[0] = 1; for(int i = 1; i <= k+2; ++i){ fac[i] = fac[i-1] * i; fac[i] %= mod; } T = 1; for(int i = 1; i <= k+2; ++i){ T *= n - i; T %= mod; }}void solve(){ if(n <= k+2){ ll res = 0; for(int i = 1; i <= n; ++i){ res += qpow(i, k, mod); res %= mod; } cout << res << endl; return; } ll res = 0; for(int i = 1; i <= k+2; ++i){ res += F[i] * T % mod * inv(n-i) % mod * inv(fac[i-1]) %mod * inv(fac[k+2-i]) %mod * ((k-i)%2 == 0?1:-1) %mod; res += mod; res %= mod; } cout << res << endl;}int main(int argc, char const *argv[]){ cin >> n >> k; init(); solve(); return 0;}Reference
- 本文题图由User
.ca - Self-made, based on Image .png,CC BY-SA 3.0,https://commons.wikimedia.org/w/index.php?curid=5538041 - 参考文章
- LaTex
Codeforces 622F The Sum of the k-th Powers
https://dicer-zz.github.io/posts/codeforces-622-f/