CF932E Team Work 数论

题目

https://codeforces.com/contest/932/problem/E

中文题面:有N(1≤N≤1e9)个不同的人,你从中选择x(x至少为1)个人去完成一个团队任务,代价为xk(1≤k≤5000)。     求所有组队方案的总代价。

关于导数四则运算:https://www.cnblogs.com/liming19680104/p/10955536.html

题解

很容易得出题目要求 ①\sum_{i=0}^{n}C_{n}^{i}i^{k},这里i=0不影响答案,

看到C_{n}^{i}很容易想到二项式定理:②(x+1)^{n}=\sum_{i=0}^{n}C_{n}^{i}x^{i}

①式和②式很像,而②式比①式好算多了,如何把②式变为①式呢?

答案是:求导

如果把②式求导后乘以x,再求导乘以x,如此重复,变为\sum_{i=0}^{n}C_{n}^{i}ix^{i}\sum_{i=0}^{n}C_{n}^{i}i^{2}x^{i}\sum_{i=0}^{n}C_{n}^{i}i^{3}x^{i}···,重复k次以后就变为\sum_{i=0}^{n}C_{n}^{i}i^{k}x^{i},由于x是我们随意取的一个数,令它等于1,②式右边最终变为\sum_{i=0}^{n}C_{n}^{i}i^{k},因此只要算②式左边求导结果就可得到答案

②式左边变换过程:

一次:(x+1)^{n}\rightarrow n(x+1)^{n-1}x

此时函数变为两个函数 n(x+1)^{n-1}x 相乘,根据导数四则运算中的d[f(x)g(x)]=f(x)d[g(x)]+g(x)d[f(x)]

可以进行如下变换:n(x+1)^{n-1}x\rightarrow n(x+1)^{n-1}x+n(n-1)(x+1)^{n-2}x^{2}

如此对形如 a_{j}(x+1)^{n-j}x^{j}( a_{j} 为该项系数)的每一项都可变为 ja_{j}(x+1)^{n-j}x^{j}+(n-j)a_{j}(x+1)^{n-(j+1)}x^{j+1}

进行k次变换,最多产生k项,其中j>n的项消去不算,用dp维护系数,复杂度O(k^{2})

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#define ll long long
#define MAXN 5005
#define MOD 1000000007ll
using namespace std;
inline ll read(){
	ll x=0,f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f*=-1;s=getchar();}
	while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+s-'0';s=getchar();}
	return x*f;
}
int k;
ll n,dp[MAXN],ans;
inline ll ksm(ll a,ll b,ll mo){
	ll res=1;
	for(;b;b>>=1){
		if(b&1)res=res*a%mo;
		a=a*a%mo;
	}
	return res;
}
int main()
{
	n=read(),k=read();
	dp[1]=n;
	for(int i=2;i<=k;i++)
		for(int j=i;j>0;j--)
			dp[j]=(dp[j-1]*(n-j+1)+dp[j]*j)%MOD;
	for(int i=1;i<=k;i++)
		if(n-i>=0)ans=(ans+dp[i]*ksm(2,n-i,MOD))%MOD;//令x等于1
	printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43960287/article/details/108931944