作为信息统练的一道题,这道题刚一出现就难倒了一批人,include me (orz。。。)
话不多说,先看题:
题目描述
给定一个多项式(by+ax)^k(by+ax)k,请求出多项式展开后x^n imes y^mxn×ym项的系数。
输入输出格式
输入格式:共一行,包含55个整数,分别为a ,b ,k ,n ,ma,b,k,n,m,每两个整数之间用一个空格隔开。
输出格式:共1 行,包含一个整数,表示所求的系数,这个系数可能很大,输出对1000710007 取模后的结果。
输入输出样例
说明
【数据范围】
对于30\%30% 的数据,有0 ≤k ≤100≤k≤10 ;
对于50\%50%的数据,有a = 1,b = 1a=1,b=1;
对于100\%100%的数据,有0≤k ≤1,000,0≤n, m≤k0≤k≤1,000,0≤n,m≤k,且n+m=k ,0 ≤a,b ≤1,000,000n+m=k,0≤a,b≤1,000,000。
如果这道题的a和b的系数为一,那么或许会好办一些,不难发现一些规律:
a+b=a+b
(a+b)^2=a^2+2ab+b^2
(a+b)^3=a^3+3a^2b+3ab^2+b^3
1 1
1 2 1
1 3 3 1
?!
似乎发现了什么秘密
如果把上面的1补全,这不就是杨辉三角吗?
其实1也是存在的,就是a+b的零次幂。
那么如果是系数不为1呢?
其实细心的朋友会发现:系数与未知数的次数应该是相同的,那么我们只要用杨辉三角得到的值再分别乘以两个系数的不同次幂的值,不就得到正确答案了吗?
那么关于系数的乘方问题,如果你只是单一的枚举每一位相乘,那么你就low爆了,不知道你听没听说过快速幂?但其实单一乘法也有它的好处:就是不用担心越界,如果用快速幂就必须考虑局部过大,所以必然要开longlong,就会废空间。各有各的好处,但我偏向于快速幂,毕竟时间就是金钱。。。(开个玩笑)
附上本题代码(福利:两种代码)
快速幂版
1 #include<cstdio> 2 using namespace std; 3 long long f[1005][1005]; 4 long long qpow(long long x,long long y) 5 { 6 long long ans=1; 7 while(y!=0) 8 { 9 if(y&1) 10 { 11 ans=(ans%10007*x%10007)%10007; 12 } 13 x=(x%10007*x%10007)%10007; 14 y>>=1; 15 } 16 return ans%10007; 17 } 18 int main() 19 { 20 int a,b,k,n,m; 21 scanf("%d%d%d%d%d",&a,&b,&k,&n,&m); 22 f[1][1]=1; 23 f[1][2]=1; 24 for(int i=2;i<=k;i++) 25 { 26 for(int j=1;j<=i+1;j++) 27 { 28 f[i][j]=(f[i-1][j]+f[i-1][j-1])%10007; 29 } 30 } 31 long long qqq=f[k][m+1]; 32 qqq=(qqq%10007*qpow(a,n)%10007)%10007; 33 qqq=(qqq%10007*qpow(b,m)%10007)%10007; 34 printf("%lld",qqq); 35 return 0; 36 }
普通版
1 #include<cstdio> 2 using namespace std; 3 int a,b,k,n,m; 4 long long f[1005][1005]; 5 int main() 6 { 7 scanf("%d%d%d%d%d",&a,&b,&k,&n,&m); 8 f[1][1]=1;f[1][2]=1; 9 for(int i=2;i<=k;i++) 10 { 11 for(int j=1;j<=i+1;j++) 12 { 13 f[i][j]=(f[i-1][j]+f[i-1][j-1])%10007; 14 } 15 } 16 int ans=f[k][m+1]; 17 for(int i=1;i<=n;i++) 18 { 19 ans=((ans%10007)*(a%10007)%10007); 20 } 21 for(int j=1;j<=m;j++) 22 { 23 ans=((ans%10007)*(b%10007)%10007); 24 } 25 printf("%d",ans); 26 return 0; 27 }