NOIP2011 计算系数 题解(超详细)

描述

给定一个多项式(ax + by)^k,请求出多项式展开后x^n * y^m项的系数。

格式

输入格式

共一行,包含5个整数,分别为a,b,k,n,m,每两个整数之间用一个空格隔开。

输出格式

输出共1行,包含一个整数,表示所求的系数,这个系数可能很大,输出对10007取模后的结果

样例1

样例输入1[复制]

1 1 3 1 2

样例输出1[复制]

3

限制

1s

提示

对于30%的数据,有0 ≤ k ≤ 10;
对于50%的数据,有a = 1, b = 1;
对于100%的数据,有0 ≤ k ≤ 1000,0 ≤ n, m ≤ k,且n+m = k,0 ≤ a,b ≤ 1,000,000.

 

分析:求系数的题目,二项式定理,杨辉三角都可以,还可以用更高级的单位根法(高数内容,高中应该预习一下)

解一:二项式定理+组合公式

C(m,n+1)=C(m,n)+C(m-1,n)

 此公式证明如下:

现在我们有n+1个球,我们从里面选m个。  这个我们知道共有C(m,n+1)种选法。  然后我们在这n+1个球里随便挑一个,叫它a球。  那么在这C(m,n+1)种选法里就分成了两类,且只有这两类。    一类是选出来的m个球里没有a球。  这类选法数量等价于n个球里选m个,就是C(m,n)  还有一类是选出来的m个球里有a球。  这类选法数量等价于n个球里选m-1个,就是C(m-1,n)

 

const mo=10007;
var
  a,b,k,n,m,i,j:longint;
  f:array[0..1000,0..1000]of int64;
begin
  read(a,b,k,n,m);
  fillchar(f,sizeof(f),0);
  f[0,0]:=1;
  for i:=1 to n do f[i,0]:=f[i-1,0];
  for i:=1 to m do f[0,i]:=f[0,i-1];
  for i:=1 to n do
    for j:=1 to m do
      f[i,j]:=(f[i-1,j] mod mo+f[i,j-1] mod mo)mod mo;//计算组合数
  for i:=1 to n do
    f[n,m]:=(f[n,m]*a) mod mo;//计算系数
  for i:=1 to m do
    f[n,m]:=(f[n,m]*b) mod mo;
  writeln(f[n,m] mod mo);
end.

解二:

快速幂+杨辉三角


const p=10007;
var a,b,n,m,k,i:longint;
tmp1,tmp2,tmp3,ans:int64;
function fast(x,n:longint):int64;
var y:int64;
begin
fast:=1;
y:=x;
while n>0 do
begin
if odd(n) then fast:=fast*y mod p;
y:=y*y mod p;
n:=n shr 1;
end;
end;

begin
assign(input,'factor.in'); reset(input);
assign(output,'factor.out'); rewrite(output);
readln(a,b,k,n,m);
tmp1:=fast(a,n);
tmp2:=fast(b,m);
tmp3:=1;
for i:=1 to n do
tmp3:=tmp3*(k-i+1)*fast(i,p-2) mod p;
ans:=tmp1*tmp2*tmp3 mod p;
writeln(ans);
close(input);
close(output);

end.

解三:纯用杨辉三角

用杨辉三角,ans=a^n*b^m*f[k,m+1]。一边计算一边摸,否则会爆。用int64.

var f:array[0..1005,0..1005]of int64;  

a,b,k,n,m,i,j:longint;  

x,y,ans:int64;

begin

//assign(input,'factor.in');

reset(input);

//assign(output,'factor.out');rewrite(output);

readln(a,b,k,n,m);

f[1,1]:=1;

for i:=2 to k+1 do  

for j:=1 to i do  

f[i,j]:=(f[i-1,j-1]+f[i-1,j])mod 10007;

x:=1;

y:=1;

for i:=1 to n do x:=x*a mod 10007;

for i:=1 to m do y:=y*b mod 10007;

ans:=x*y*f[k+1,m+1] mod 10007;

writeln(ans);

//close(input);close(output);

end.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值