算法:真·滚动数组模拟!!!
马上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; }
注意:计算时时时刻刻取余以保证代码正确性!!!