您的位置:首页 > 其它

codeforces 932E Team Work 高等数学求导、dp

2018-02-19 17:38 337 查看

题解

这是一道纯粹的数学求导题目。

首先我们先写出要求的公式。

ans=∑nr=1Crnrkans=∑r=1nCnrrk

乍一看,雾草好吓人,但是学过高等数学且稍有常识的人(不是我)可以看出,这个可以由某个式子不断乘x并求导得出来。

没错,稍有常识的人又可以看出来了,这个式子就是(1+x)n(1+x)n

(1+x)n=∑nr=0Crnxr(1+x)n=∑r=0nCnrxr

我们定义 f0=ddx(1+x)n=n(1+x)n−1f0=ddx(1+x)n=n(1+x)n−1

同时f0(x)=∑nr=1Crnrxr−1f0(x)=∑r=1nCnrrxr−1

定义ft(x)=ddx(xft−1(x))ft(x)=ddx(xft−1(x))

这样的话fk−1(x)=∑nr=1Crnrkfk−1(x)=∑r=1nCnrrk

那么我们要求的答案ans=f(0)k−1(1)ans=fk−1(0)(1)

我们知道ft(x)=ddx(xft−1(x))=ft−1(x)+xf(1)t−1(x)ft(x)=ddx(xft−1(x))=ft−1(x)+xft−1(1)(x)

通过这个操作,f(p)t(1)=(p+1)f(p)t−1(1)+f(p+1)t−1(1)ft(p)(1)=(p+1)ft−1(p)(1)+ft−1(p+1)(1)

没错!这就是我们的递推公式!

定义dp[i][j]=f(j)i(1)dp[i][j]=fi(j)(1)

dp[i][j]=(p+1)∗dp[t−1][p]+dp[t−1][p+1]dp[i][j]=(p+1)∗dp[t−1][p]+dp[t−1][p+1]

由于我们只需要ans=dp[k−1][0]ans=dp[k−1][0],那么就只需要dp[k−2][0...1]dp[k−2][0...1],…,只需要dp[0][0...k−1]dp[0][0...k−1]

状态数O(K2)O(K2)

代码

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll N,k;
const ll mod = 1e9+7;
const int maxn = 5007;
ll dp[maxn][maxn],sum[maxn];
ll mod_pow(ll x,ll n){
ll ans = 1;
while(n){
if(n&1)
ans = ans * x % mod;
x = x*x%mod;
n >>= 1;
}
return ans;
}
int main(){
cin>>N>>k;
if(N == 1){
return 0*printf("1\n");
}
ll pre = N;
for(int t = 0;t < min(N,5005ll);++t){
dp[0][t] = pre*mod_pow(2,N-1-t)%mod;
pre = pre*(N-1-t)%mod;
}
for(int i = 1;i <= k;++i){
for(int j = 0;j <= k;++j){
dp[i][j] = ((j+1)*dp[i-1][j] + dp[i-1][j+1])%mod;
}
}
printf("%lld\n",dp[k-1][0]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: