洛谷 P1313 计算系数

                               

  要求二项式的幂的某个系数的话,到了初中就应该会知道可以用 杨辉三角 这个东西来求系数。举几个例子吧:

1                     1                    
2                  1     1                  
3               1     2     1             (a+b)^2=a^2+2ab+b^2
4            1     3     3     1          (a+b)^3=a^3+3ba^2+3ab^2+b^3
5         1     4     6     4     1                ……                
6      1     5     10    10    5    1              ……          

  根据这两个例子就能看出:杨辉三角的第 n 行对应的就是 (a+b)的 n-1 次方的各项系数。再看杨辉三角的规律:每一项都是这一项岁对应的上面两个数的和,所以我们可以打印杨辉三角,在做些运算就可以A掉这个题啦。

  先说怎么求杨辉三角,一般都是定义一个二维数组,假设为 a[][];根据杨辉三角的规律,可以得到一个递推式:

                                  a[i][j]=a[i-1][j-1]+a[i-1][j];

  不要忘了先将 a[1][1]赋值为 1

代码:

 

1     a[1][1]=1;
2     for(int i=2;i<=k+1;++i) // k是(a+b)的次数
3     {
4         for(int j=1;j<=k+1;++j)
5         {
6             a[i][j]=a[i-1][j-1]+a[i-1][j];
7         }
8     }

 

注意:i 要从2开始循环,因为 a[1][1]已经赋值了,如 i 从1开始的话,a[1][1]会被重新赋值为0,这样打印出来就都是0;

  虽然这种打印杨辉三角的方法没有任何问题,但是看数据范围:

              

 

  k≤10000,这样的话就数组就至少要开 a[10000][10000];而且仅是 int 类型的话这个二维数组所占内存为:                                      10000×10000×4÷1024÷1024≈381.47MB;

  将近是内存限制的3倍,这肯定不行,所以就有了另一种内存占用比较少的方法:既然我们只需要杨辉三角的第 k+1 行,所以我们可以定义一个一维数组来存储 k=1时的数,推出 k=2时的数后,再将这个一维数组更新,这样不断更新来减少内存;

  代码:

 1     a[1]=1; // 依旧要赋值为1
 2     b[1]=1; // 同上
 3     for(int i=2;i<=k+1;++i) // i代表 当(a+b)为 i 次方时
 4     {
 5         for(int j=2;j<=i+1;++j) // 当(a+b)为 i 次方时,展开后一共会有 i+1 项,因为第一项的系数始终为1,所以数组从 2 到 i+1 更新
 6         {
 7             a[j]=b[j-1]+b[j]; // 递推式
 8         }
 9         for(int j=2;j<=i+1;++j) // 将本次循环所更新后的数储存,以便下一次的递推
10         {
11             b[j]=a[j]; // 进行赋值
12         }
13     }

  定义了两个数组,a[10010] 和 b[10010],a来存储当前的数值,b来存储上一次的数值,用来递推。所以最终a数组存储的就是(a+b)^k的每项系数。

  (a+b)^k的系数求出来后,不要忘了题目中要求求的是(by+ax)^k展开后 x^n*y^m项的系数。这个系数其实就是b^m*a^n*a[m+1]或者是b^m*a^n*a[n+1];

完整代码:

 1 #include<iostream>
 2 using namespace std;
 3 long long a[10010];
 4 long long b[10010];
 5 const long long mod=10007;// 要求对10007取余
 6 int main()
 7 {
 8     a[1]=1;
 9     b[1]=1;
10     long long a2,b2,a1,b1,k,n,m;
11     cin>>a1>>b1>>k>>n>>m;
12     if(n==0 && m==0) // 特判
13     {
14         cout<<"0";
15         return 0;
16     }
17     a1%=mod,b1%=mod;
18     a2=a1,b2=b1;
19     for(int i=2;i<=k+1;++i)
20     {
21         for(int j=2;j<=i+1;++j)
22         {
23             a[j]=(b[j-1]+b[j])%mod; // 分步取模,防止炸long long
24             a[j]%=mod;
25         }
26         for(int j=2;j<=i+1;++j)
27         {
28             b[j]=a[j]%mod;
29         }
30     }
31     for(int i=2;i<=n;++i)
32     {
33         a1*=a2;
34         a1%=mod;
35     }
36     for(int i=2;i<=m;++i)
37     {
38         b1*=b2;
39         b1%=mod;
40     }
41     long long ans=((a[m+1]*a1)%mod*b1)%mod;
42     cout<<ans;
43     return 0;
44 }

 

posted @ 2020-05-02 16:14  zkw666  阅读(278)  评论(0编辑  收藏  举报