Lust(Codeforces Round #446 Div.1-891E)(母函数\生成函数)

23 篇文章 0 订阅
8 篇文章 0 订阅

文章目录

题目

你有n个数 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an ,要进行 k k k 次操作,每次在 1 1 1 ~ n n n 中随机选择一个数 x x x,使得 r e s + = ∏ i ! = x a i res+=\prod_{i!= x}a_i res+=i!=xai ,然后 a x a_x ax 减少 1 1 1,求最后 r e s res res 值的期望,答案对 1 0 9 + 7 10^9+7 109+7 取模。
数据范围:
1 ≤ n ≤ 5000 , 1 ≤ k ≤ 1 0 9 , 0 ≤ a i ≤ 1 0 9 1\le n\le 5000,1\le k \le 10^9,0\le a_i\le 10^9 1n5000,1k109,0ai109

思路

我们考虑在某一个局面即将进行一次操作:
记现在 a i a_i ai 减少的次数为 b i b_i bi ,我们选中 a x a_x ax
那我们计算一次答案贡献:
∏ i ! = x ( a i − b i ) , 同 时 b x + = 1 \prod_{i!=x}(a_i-b_i),同时b_x+=1 i!=x(aibi),bx+=1
那么我们变形
( ( a x − b x ) − ( a x − ( b x + 1 ) ) ) ∗ ∏ i ! = x ( a i − b i ) ((a_x-b_x)-(a_x-(b_x+1)))*\prod_{i!=x}(a_i-b_i) ((axbx)(ax(bx+1)))i!=x(aibi)
∏ i = 1 n ( a i − b i ) − ( ∏ i = 1 n ( a i − b i ) ) ∗ ( a x − ( b x + 1 ) ) \prod_{i=1}^n(a_i-b_i)-(\prod_{i=1}^n(a_i-b_i))*(a_x-(b_x+1)) i=1n(aibi)(i=1n(aibi))(ax(bx+1))
我们记某一个局面 α = ( b 1 , b 2 , . . . , b n ) \alpha=(b_1,b_2,...,b_n) α=(b1,b2,...,bn)
我们记 f ( α ) = ∏ i = 1 n ( a i − b i ) f(\alpha)=\prod_{i=1}^n(a_i-b_i) f(α)=i=1n(aibi)
那么一次的贡献为: f ( α ) − f ( β ) f(\alpha)-f(\beta) f(α)f(β)
初局面:
f ( s t a r t ) = ∏ i = 1 n a i f(start)=\prod_{i=1}^na_i f(start)=i=1nai
于是类似于裂项相消的样子,我们只剩初局面和末局面


E = f ( s t a r t ) − ∑ k ! n k ∗ ∏ i = 1 n b i ! ∗ f ( e n d ) E=f(start)-\sum\frac{k!}{n^k*\prod_{i=1}^nb_i!}* f(end) E=f(start)nki=1nbi!k!f(end)
于是我们只需保证: ∑ i = 1 n b i = k \sum_{i=1}^nb_i=k i=1nbi=k
化简后半段
∑ k ! n k ∗ ∏ i = 1 n b i ! ∗ ∏ i = 1 ( a i − b i ) = k ! n k ∗ ∑ ∏ i = 1 a i − b i b i ! \sum\frac{k!}{n^k*\prod_{i=1}^nb_i!}*\prod_{i=1}(a_i-b_i)=\frac{k!}{n^k}*\sum\prod_{i=1}\frac{a_i-b_i}{b_i!} nki=1nbi!k!i=1(aibi)=nkk!i=1bi!aibi
发现这个似乎很难搞,我们考虑化简和指数型母函数构造:
G ( x ) = ∏ i = 1 n ∑ j = 0 + ∞ a i − j j ! x j G(x)=\prod_{i=1}^n\sum_{j=0}^{+\infty}\frac{a_i-j}{j!}x^j G(x)=i=1nj=0+j!aijxj
= ∏ i = 1 n ∑ j = 0 + ∞ ( a i j ! x j − j j ! x j ) =\prod_{i=1}^n\sum_{j=0}^{+\infty}(\frac{a_i}{j!}x^j-\frac{j}{j!}x^j) =i=1nj=0+(j!aixjj!jxj)
= ∏ i = 1 n ( ∑ j = 0 + ∞ a i j ! x j − ∑ j = 0 + ∞ x j ! x j ) =\prod_{i=1}^n(\sum_{j=0}^{+\infty}\frac{a_i}{j!}x^j-\sum_{j=0}^{+\infty}\frac{x}{j!}x^j) =i=1n(j=0+j!aixjj=0+j!xxj)
= ∏ i = 1 n ( ( a i − x ) ∗ ∑ j = 0 + ∞ x j j ! ) =\prod_{i=1}^n((a_i-x)*\sum_{j=0}^{+\infty}\frac{x^j}{j!}) =i=1n((aix)j=0+j!xj)
= ∏ i = 1 n ( ( a i − x ) ∗ e x ) =\prod_{i=1}^n((a_i-x)*e^x) =i=1n((aix)ex)
= e n x ∏ i = 1 n ( a i − x ) =e^{nx}\prod_{i=1}^n(a_i-x) =enxi=1n(aix)
我们的目标是求 G ( x ) G(x) G(x) 的第 k k k 项系数 f k f_k fk,考虑将后面直接 O ( n 2 ) O(n^2) O(n2) 拆成多项式形式(当然你会分治FFT O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)):
G ( x ) = e n x ∗ ∑ i = 0 n c i ∗ x i G(x)=e^{nx}*\sum_{i=0}^nc_i*x^i G(x)=enxi=0ncixi
前面拆开:
G ( x ) = ( 1 + n x 1 ! + ( n x ) 2 2 ! + . . . ) ∗ ∑ i = 0 n c i ∗ x i G(x)=(1+\frac{nx}{1!}+\frac{(nx)^2}{2!}+...)*\sum_{i=0}^nc_i*x^i G(x)=(1+1!nx+2!(nx)2+...)i=0ncixi
我们要求第 k k k 项的系数 g k g_k gk
g k = ∑ i = 0 n c i ∗ n k − i ( k − i ) ! g_k=\sum_{i=0}^nc_i*\frac{n^{k-i}}{(k-i)!} gk=i=0nci(ki)!nki
回代到答案的后半段:
k ! n k ∗ ∑ ∏ i = 1 a i − b i b i ! = k ! n k ∗ g k \frac{k!}{n^k}*\sum\prod_{i=1}\frac{a_i-b_i}{b_i!}=\frac{k!}{n^k}*g_k nkk!i=1bi!aibi=nkk!gk
= k ! n k ∗ ∑ i = 0 n c i ∗ n k − i ( k − i ) ! =\frac{k!}{n^k}*\sum_{i=0}^nc_i*\frac{n^{k-i}}{(k-i)!} =nkk!i=0nci(ki)!nki
我们知道 n n n 相较于 k k k 很小 于是继续化简:
= ∑ i = 0 n c i ∗ A k i n i =\sum_{i=0}^nc_i*\frac{A_k^i}{n^i} =i=0nciniAki
最后这个式子我们可以考虑递推 O ( n ) O(n) O(n) 计算
总时间复杂度: O ( n 2 ) / O ( n l o g 2 n ) O(n^2)/O(nlog^2n) O(n2)/O(nlog2n)

代码

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<deque>
#include<cstdio>
#include<ctime>
#include<bitset>
#include<vector>
#include<climits>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
#define ULL unsigned long long
LL read(){
	LL f=1,x=0;char c=getchar();
	while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
	while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
	return f*x;
}
#define MAXN 5000
#define INF 0x3f3f3f3f
#define Mod (LL)(1e9+7)
LL Pow(LL x,LL y){
	LL ret=1;
	while(y){
		if(y&1) ret=ret*x%Mod;
		x=x*x%Mod;
		y>>=1;
	}
	return ret;
}
LL a[MAXN+5],b[MAXN+5],c[MAXN+5];
int main(){
	LL n=read(),k=read(),ans=1;
	for(int i=1;i<=n;i++)
		a[i]=read(),ans=ans*a[i]%Mod;
	c[0]=1;
	for(int i=1;i<=n;i++){
		for(int j=0;j<i;j++)
			b[j]=c[j]*a[i]%Mod;
		for(int j=0;j<i;j++)
			b[j+1]=(b[j+1]-c[j]+Mod)%Mod;
		memcpy(c,b,sizeof(c));
	}
	LL f=0,t1=1,t2=1,invn=Pow(n,Mod-2);
	for(int i=0;i<=n;i++){
		f=(f+c[i]*t1%Mod*t2%Mod)%Mod;
		t1=t1*(k-i)%Mod,t2=t2*invn%Mod;
	}
	ans=(ans-f)%Mod;
	printf("%lld\n",(ans+Mod)%Mod);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Lust伺服调试软件是一种可用于伺服系统的调试和优化的软件工具。它提供了一个直观和用户友好的界面,用于监测和控制伺服系统的操作。通过该软件,用户可以实时查看伺服系统的状态和参数,并进行实时反馈控制和调整。 Lust伺服调试软件的主要功能包括以下几个方面: 1. 参数设置:用户可以通过该软件设置伺服系统的工作参数,包括速度、加速度、位置等。通过调整这些参数,用户可以优化伺服系统的运行效果,使其更适应不同的工作需求。 2. 监控和调试:软件提供了实时监测和显示伺服系统的工作状态和各种参数。用户可以通过图表和曲线来查看伺服系统的运行情况,以便判断系统是否正常工作。如果出现问题,用户可以通过软件提供的故障诊断功能进行调试和修复。 3. 运动控制:软件提供了丰富的运动控制功能,用户可以通过简单的操作来控制伺服系统进行运动。通过输入指定的位置、速度和加速度,软件会根据设定的参数控制伺服系统实现精确的运动。 4. 数据记录和分析:软件还提供了数据记录和分析的功能,用户可以将伺服系统的工作数据记录下来,以便后期分析和优化。通过这些数据,用户可以了解到伺服系统的工作情况和优化的方向。 总之,Lust伺服调试软件是一款功能强大的工具,能够帮助用户对伺服系统进行调试和优化。它提供了直观的界面和丰富的功能,使得用户能够轻松监控和控制伺服系统的运行,并进行合理的调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值