NOIP 2011 提高组 计算系数(vijos 1739)(方法:二项式定理)
<————————————————————————————————————————————————————————>
附: 题目链接 vijos 1739 地址:https://www.vijos.org/p/1739
<————————————————————————————————————————————————————————>
PS:本题关键是二次项定理:,其中,
又有
(即组合数)等记法。
由二次项定理推结果:
令 c = ax; d = by; 原式 变为 ( c + d ) k,
则 cn * dm 的系数 为 C(k,m)
—> anxn * bmym 的系数 为 C(k , m)
—> xn ym 的系数 为 an * bm * C(k , m)
则 求 C(k , m) 成为了结题关键,按照常规算法, C(k , m) = m! / ( k! * (m-k)! )
但 很显然 直接累乘 会爆范围 ( 过程中不能mod,因为还要约分母)
所以 这题最好用 组合 的递推算法: C(n , m) = C(n-1 , m) + C(n-1 , m-1)
该题解采用 滚动数组 以节省空间。 (值得一提的是 k<=1000 , m<=k)
<————————————————————————————————————————————————————————>
const mo=10007; //要求的取mod
var
c:array[0..1,0..1000] of longint; //滚动数组 求 组合
a,b,k,n,m,i,j,new,old:longint; //new为 当前决策点,old 为上一决策点
begin
readln(a,b,k,n,m);
a := a mod mo;
b := b mod mo; //值得一提的是,a、b没mod后几个数据会爆longint,如vijos上不加只能有80 - =
c[0,0] := 1;
c[1,0] := 1;
<————————————————————————————————————————————————————————>
读入数据,并对a,b进行处理,当然也可不处理,采用int64
<————————————————————————————————————————————————————————>
for i := 1 to k do begin
new:=1-new;
old:=1-new;
for j := 1 to m do if i >= j then //记得加 i>=j 0 0,否则组合会求错 - =
c[new,j] := (c[old,j-1] + c[old,j]) mod mo;
end;
<————————————————————————————————————————————————————————>
滚动数组求组合,过程中不边算边mod也会爆范围 - =
<————————————————————————————————————————————————————————>
j := c[new,m];
for i := 1 to n do j := (j * a) mod mo;
for i := 1 to m do j := (j * b) mod mo;
writeln(j);
<————————————————————————————————————————————————————————>
乘a^n,b^m,得最后结果,同样边乘边mod,理由同上
<————————————————————————————————————————————————————————>
end.
<————————————————————————————————————————————————————————>
End。