洛谷P5087 数学

题目链接


思路:一个很容易想的DP

f i , j f_{i,j} fi,j 表示在前 i i i 个数中取 j j j 个所得到的乘积。

f i , j = f i − 1 , j + f i − 1 , j − 1 × a i ( i > 0 , j > 0 ) f_{i,j}=f_{i-1,j}+f_{i-1,j-1}×a_i \quad(i>0,j>0) fi,j=fi1,j+fi1,j1×ai(i>0,j>0)
边界: f 0 , 0 = 1 f 0 , i = 0   ( i ≠ 0 ) f i , 0 = 0   ( i ≠ 0 ) f_{0,0}=1\quad f_{0,i}=0\ (i\ne0) \quad f_{i,0}=0\ (i\ne 0) f0,0=1f0,i=0 (i̸=0)fi,0=0 (i̸=0)

但是直接DP会爆空间。。。
观察到DP时只需调用到 f i − 1 f_{i-1} fi1 ,所以可以用滚动数组的方式优化空间。

代码时间复杂度 O ( n k ) \mathcal O(nk) O(nk),空间复杂度 O ( n + k ) \mathcal O(n+k) O(n+k)

const
	mo=1000000007; //膜数
var
	n,k,i,j:longint;
	a:array[0..100010] of longint;
	f1,f2:array[0..500] of int64; //安全起见开int64
begin
	readln(n,k);
	for i:=1 to n do read(a[i]);
	f1[0]:=1; //边界初始化
	for i:=1 to n do //DP
	begin
		for j:=0 to k do
			f2[j]:=(f1[j]+f1[j-1]*a[i]) mod mo;
		f1:=f2;
	end;
	writeln(f1[k]);
end.

做完题后仔细想了一下,发现 a \rm a a 数组的空间也是可以省掉的,在线处理就可以,不用存。
然后就有了空间复杂度 $\mathcal O(k) $ 的代码:

const mo=1000000007;
var
    n,k,i,j,a:longint;
    f1,f2:array[0..500] of int64;
begin
    readln(n,k);
    f1[0]:=1;
    for i:=1 to n do
    begin
        read(a); //这样就可以把a压成变量了QAQ
        for j:=0 to k do
            f2[j]:=(f1[j]+f1[j-1]*a) mod mo;
        f1:=f2;
    end;
    writeln(f1[k]);
end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值