P1313 [NOIP2011 提高组] 计算系数
题目描述
给定一个多项式 ( b y + a x ) k (by+ax)^k (by+ax)k ,请求出多项式展开后 x n × y m x^n\times y^m xn×ym项的系数。
输入格式
共一行,包含 5 5 5个整数,分别为 a a a , b b b , k k k , n n n , m m m每两个整数之间用一个空格隔开。
输出格式
共 1 1 1 行,包含一个整数,表示所求的系数,这个系数可能很大,输出对 10007 10007 10007取模后的结果。
输入样例
1 1 3 1 2
输出样例
3
说明/提示
【数据范围】
对于 30 % 30\% 30% 的数据,有 0 ≤ k ≤ 100 ≤ k ≤ 10 0 ≤k ≤100≤k≤10 0≤k≤100≤k≤10 ;
对于 50 % 50\% 50%的数据,有 a = 1 , b = 1 a = 1,b = 1 a=1,b=1;
对于 100 % 100\% 100%的数据,有 0 ≤ k ≤ 1 , 000 0≤k ≤1,000 0≤k≤1,000; 0 ≤ n , m ≤ k 0≤n, m≤k 0≤n,m≤k,且 n + m = k n+m=k n+m=k, 0 ≤ a , b ≤ 1 , 000 , 000 0 ≤a,b ≤1,000,000 0≤a,b≤1,000,000。
noip2011提高组day2第1题
思路一
x
n
×
y
m
x^n\times y^m
xn×ym项的系数为
C
k
m
×
b
m
×
a
n
C_k^m\times b^m\times a^n
Ckm×bm×an。根据组合数的性质,有
C
n
m
=
C
n
−
1
m
−
1
+
C
n
−
1
m
C_n^m=C_{n-1}^{m-1}+C_{n-1}^m
Cnm=Cn−1m−1+Cn−1m可以用动态规划的方法计算
C
k
m
C_k^m
Ckm:
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
−
1
]
+
d
p
[
i
−
1
]
[
j
]
dp[i][j]=dp[i-1][j-1]+dp[i-1][j]
dp[i][j]=dp[i−1][j−1]+dp[i−1][j]其中
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]代表
C
i
j
C_i^j
Cij,注意
d
p
[
0
]
[
0
]
=
1
dp[0][0]=1
dp[0][0]=1以及取余就可以了。
一个平平无奇的代码:
#include<cstdio>
using namespace std;
const int maxn=1005,mod=10007;
int dp[maxn][maxn],a,b,k,n,m;
signed main(){
scanf("%d%d%d%d%d",&a,&b,&k,&n,&m);
dp[0][0]=1;
for(int i=1;i<=1000;i++){
for(int j=0;j<=i;j++){
dp[i][j]=(dp[i][j]+dp[i-1][j])%mod;
if(j>=1) dp[i][j]=(dp[i][j]+dp[i-1][j-1])%mod;
}
}
a=a%mod; b=b%mod;
int am=1,bm=1;
for(int i=1;i<=m;i++) bm=(bm*b)%mod;
for(int i=1;i<=n;i++) am=(am*a)%mod;
a=am*bm%mod*dp[k][m]%mod;
printf("%d",a);
}
可以用快速幂计算 a n a^n an和 b m b^m bm,不过k最大为1000,直接算也可以。
思路二
前面分析到,答案为
C
k
m
×
b
m
×
a
n
C_k^m\times b^m\times a^n
Ckm×bm×an,关键在于计算
C
k
m
C_k^m
Ckm。可以根据定义,
C
k
m
=
k
!
(
k
−
m
)
!
m
!
C_k^m=\frac{k!}{(k-m)!m!}
Ckm=(k−m)!m!k!。
因为
k
!
(
k
−
m
)
!
m
!
=
k
!
[
(
k
−
m
)
!
m
!
]
−
1
,
(
m
o
d
=
10007
)
\frac{k!}{(k-m)!m!}=k![(k-m)!m!]^{-1},(mod=10007)
(k−m)!m!k!=k![(k−m)!m!]−1,(mod=10007),由于10007为质数,所以
k
!
(
k
−
m
)
!
m
!
=
k
!
[
(
k
−
m
)
!
m
!
]
−
1
=
k
!
[
(
k
−
m
)
!
m
!
]
m
o
d
−
2
,
(
m
o
d
=
10007
)
\frac{k!}{(k-m)!m!}=k![(k-m)!m!]^{-1}=k![(k-m)!m!]^{mod-2},(mod=10007)
(k−m)!m!k!=k![(k−m)!m!]−1=k![(k−m)!m!]mod−2,(mod=10007)。
#include<cstdio>
using namespace std;
const int mod=10007,maxn=1e6+5;
int a,b,k,n,m,f[maxn]={1};
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1) ans=ans*a%mod;
a=a*a%mod,b>>=1;
}
return ans;
}
int main(){
for(int i=1;i<maxn;i++) f[i]=f[i-1]*i%mod;
scanf("%d%d%d%d%d",&a,&b,&k,&n,&m);
a%=mod; b%=mod;
a=qpow(a,n); b=qpow(b,m);
int t=f[k-m]*f[m]%mod;
t=qpow(t,mod-2);
printf("%d\n",((f[k]*t%mod)*b%mod)*a%mod);
}