计算系数

算法:真·滚动数组模拟!!!

马上CSP/S了,这是远在今年暑假前的一天的校内考试题中的一道。当时做的时候不会组合数,不会二项式定理,不会DP,不会……只知道应该n*n的空间存一个杨辉三角形图,然后依次读取。

然而考场上发现这个可以优化,并滚键盘滚出了下面的那一坨东西居然对了:只需2个数组就可以存下整个题目所需要的杨辉三角形:杨辉三角形的长度和k有关,比如:

3——1 2 1,长度3

4——1 3 3 1,长度4

……

可见k为奇数,则杨辉三角形长度为奇数,反之为偶数。

我们要求第k层的杨辉三角形。在计算的过程中,下一层需要从上一层的杨辉三角形转移而来(dp思想?!),而上下两层奇偶不同,其长度必然不同,于是我们用2个数组不停滚动,就能正确求得要的那层杨辉三角形。

#include<bits/stdc++.h>
using namespace std;
int f1=1,f2=1,a,b,k,n,m,ans,yh[1005]= {0,1},yh2[1005]= {0,1};
void yanghui(int x)
{
    if(x%2==0)//层数为偶数
        for(int i=2; i<=x+1; i++)//为什么i=2开始?因为杨辉三角形每层的第一个数必定是1
            yh2[i]=(yh[i-1]+yh[i])%10007;//从上一层下来
    else if(x%2==1)//层数为奇数
        for(int i=2; i<=x+1; i++)
            yh[i]=(yh2[i-1]+yh2[i])%10007;//同上
    if(x+1!=k)yanghui(x+1);//只要层数不到k,我们就继续转移
}
int fang()
{
    for(int i=1; i<=n; i++)
        f1=(f1*a)%10007;
    for(int i=1; i<=m; i++)
        f2=(f2*b)%10007;
    return (f1*f2)%10007;
   //朴素乘运算。有兴趣你可以造个快速幂什么的
}
int main()
{
    //freopen("factor.in","r",stdin);
    //freopen("factor.out","w",stdout);freopen注释
    scanf("%d%d%d%d%d",&a,&b,&k,&n,&m);
    a=a%10007,b=b%10007;//千万要读入取模!!考场忘记取模80分,回家取模AC
    if(k==0||k==1)//特判2种情况
    {
        cout<<0;
        return 0;
    }
    k++;//请思考为什么要k++ k--
    yanghui(1);//制造杨辉三角形
    k--;
    if(k%2==1)ans=(fang()*yh[n+1])%10007;
    if(k%2==0)ans=(fang()*yh2[k-n+1])%10007;//计算系数,判断k的奇偶
    printf("%d",(ans+10007)%10007);
   //时时刻刻取余以保证代码正确性
   return 0;
}

注意:计算时时时刻刻取余以保证代码正确性!!!

注意:读入a、b要取余!!!

01-01 18:18