【NOIP2011提高组】计算系数

时间:2023-03-09 15:46:55
【NOIP2011提高组】计算系数

计算系数

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

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

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

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