计算系数(NOIP2011 day2)

给定一个多项式 (ax + by)k

输入a,b,k,n,m。

请求出多项式展开后 xnym 项的系数。

【数据范围】
对于 30%的数据,有 0≤k≤10;
对于 50%的数据,有 a = 1,b = 1;
对于 100%的数据,有 0≤k≤1,000,0≤n, m≤k,且 n + m = k,0≤a,b≤1,000,000。

分析:

根据二项式定理可知:xnym的系数是C(k,n)*an*bm

关键是求C(k,n)的值:

方法一:

本题中k(<=1000)的值比较小,可以利用递推式C(k,n)=C(k-1,n-1)+C(k-1,n)直接求得。

 1 const
 2   maxn=1000;
 3   md=10007;
 4 var
 5   f:array[0..maxn,0..maxn] of longint;
 6   a,b,n,k,m,s,i,j:longint;
 7 begin
 8   assign(input,'factor.in'); reset(input);
 9   assign(output,'factor.out'); rewrite(output);
10   readln(a,b,k,n,m);
11   a:=a mod md;
12   b:=b mod md;
13   f[0,0]:=1;
14   for i:=1 to k do begin f[i,0]:=1; f[i,i]:=1; end;
15   for i:=2 to k do
16     for j:=1 to i-1 do f[i,j]:=(f[i-1,j]+f[i-1,j-1])mod md;
17   s:=1;
18   for i:=1 to n do s:=(s*a)mod md;
19   for i:=1 to m do s:=(s*b)mod md;
20   writeln((f[k,n]*s)mod md);
21 end.
View Code

方法二:

如果k的范围再大的话,如k<=50000,就无法直接使用方法一中的递推式。

另一种解决问题的方法是:根据组合公式C(k,n)=(k*(k-1)*...*(k-n+1))/(1*2*...*n)

分子和分母分解质因数后约分即可(当然要先求出k以内的素数)。

 1 const
 2   maxk=100000;
 3   md=10007;
 4   fin='factor.in';
 5   fout='factor.out';
 6 var
 7   p,e:array[1.. maxk] of longint;
 8   f:array[1..maxk] of boolean;
 9   a,b,k,n,m,cnt,s:longint;
10   procedure init;
11     begin
12       assign(input,fin); reset(input);
13       readln(a,b,k,n,m);
14       a:=a mod md;
15       b:=b mod md;
16       close(input);
17     end;
18   procedure make_p;//生成素数表
19     var i,j:longint;
20     begin
21       fillchar(f,sizeof(f),true);
22       cnt:=0;
23       for i:=2 to k do
24         if f[i] then
25           for j:=2 to k div i do f[i*j]:=false;
26       for i:=2 to k do
27         if f[i] then
28           begin inc(cnt); p[cnt]:=i; end;
29     end;
30   procedure make_e; //生成指数
31     var i,j,now:longint;
32     begin
33       fillchar(e,sizeof(e),0);
34       for i:=k-n+1 to k do  //处理分子指数
35         begin
36           j:=i; now:=1;
37           while j>1 do
38             begin
39               while j mod p[now]=0 do
40                 begin inc(e[now]); j:=j div p[now]; end;
41               inc(now);
42             end;
43         end;
44       for i:=1 to n do     //处理分母指数
45         begin
46           j:=i; now:=1;
47           while j>1 do
48             begin
49               while j mod p[now]=0 do
50                 begin dec(e[now]); j:=j div p[now]; end;
51               inc(now);
52             end;
53         end;
54       end;
55   procedure calc;
56     var i,j:longint;
57     begin
58       s:=1;
59       for i:=1 to cnt do
60         if e[i]>0 then
61           for j:=1 to e[i] do s:=(s*p[i])mod md;
62       for i:=1 to n do s:=(s*a)mod md;
63       for i:=1 to m do s:=(s*b)mod md;
64     end;
65   procedure print;
66     begin
67       assign(output,fout); rewrite(output);
68       writeln(s);
69       close(output);
70     end;
71 begin
72   init;
73   make_p;
74   make_e;
75   calc;
76   print;
77 end.
View Code

 

 

 

posted on 2014-06-19 19:36  ssfzzzc  阅读(413)  评论(0)    收藏  举报

导航