题目描述
给定一个多项式 (by+ax)^k(by+ax)k,请求出多项式展开后 x^n\times y^mxn×ym 项的系数。
输入格式
输入共一行,包含 55 个整数,分别为 a,b,k,n,ma,b,k,n,m,每两个整数之间用一个空格隔开。
输出格式
输出共一行,包含一个整数,表示所求的系数。
这个系数可能很大,输出对 1000710007 取模后的结果。
输入输出样例
输入 #1复制
1 1 3 1 2
输出 #1复制
3
说明/提示
【数据范围】
对于 30\%30% 的数据,有 0\le k\le 100≤k≤10。
对于 50\%50% 的数据,有 a=1a=1,b=1b=1。
对于 100\%100% 的数据,有 0\le k\le 10000≤k≤1000,0\le n,m\le k0≤n,m≤k,n+m=kn+m=k,0\le a,b\le 10^60≤a,b≤106。
noip2011 提高组 day2 第 1 题。
1.
——这一道题目,看别人都是用杨辉三角做的,可偏偏我这个菜鸟不会。于是就打了个类似于dp的做法。
——f[i][j]表示x^iy^j的系数,(默认k=i+j),可以得到转移:f[i][j]=f[i-1][j]*a+f[i][j-1]*b;
——于是大致的思路就好啦,然后是细节,如f[0][0]是1,这类的要注意
代码如下
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int a,b,k,n,m;
long long f[1005][1005];
int main()
{
scanf("%d%d%d%d%d",&a,&b,&k,&n,&m);
f[0][0]=1;
for (int i=0;i<=n;i++)
for (int j=0;j<=m;j++)
{
if (i==0 && j==0) continue;
f[i][j]=0;
if (i>0)
f[i][j]=(f[i][j]+f[i-1][j]*a)%10007;
if (j>0)
f[i][j]=(f[i][j]+f[i][j-1]*b)%10007;
}
printf("%lld\n",f[n][m]);
return 0;
}
2.
Solution
根据二项式定理,
(a+b)^n=\sum_{k=0}^nC_{n}^{k}a^kb^{n-k}(a+b)n=k=0∑nCnkakbn−k
那么
(ax+by)^k=\sum_{p=0}^kC_{k}^p(ax)^p(by)^{k-p}=\sum_{p=0}^k(C_{k}^pa^pb^{k-p})x^py^{k-p}(ax+by)k=p=0∑kCkp(ax)p(by)k−p=p=0∑k(Ckpapbk−p)xpyk−p
算a^n,b^man,bm需要用快速幂.
- 可以根据组合式的递推公式算组合数.我是这么写的.
C_n^m=C_{n-1}^m+C_{n-1}^{m-1}Cnm=Cn−1m+Cn−1m−1
- 或者是利用组合数的定义式,但是因为有取余, 所以要用逆元.
C_n^m=\frac{n!\mod 10007}{m!(n-m)!\mod 10007}=n!\times [m!(n-m)!]^{-1}\mod 10007Cnm=m!(n−m)!mod10007n!mod10007=n!×[m!(n−m)!]−1mod10007
其中[m!(n-m)!]^{-1}[m!(n−m)!]−1为逆元, 这个可以直接用费马小定理, 正好前面写了快速幂, 岂不是美滋滋.
Code
#include<cstdio>
#define N 1005
#define mod 10007
using namespace std;
#define int long long
int c[N][N];
int a,b,k,n,m;
int pow(int x,int y){
int ans=1,pas=x;
while(y){
if(y&1)ans*=pas%mod,ans%=mod;
pas=(pas*pas)%mod;
y>>=1;
}
return ans%mod;
}
int dfs(int n,int m){
if(!m)return c[n][m]=true;if(m==1)return c[n][m]=n;
if(c[n][m])return c[n][m];
if(n-m<m)m=n-m;
return c[n][m]=(dfs(n-1,m)+dfs(n-1,m-1))%mod;
}
main(){
//freopen("factor.in","r",stdin);
//freopen("factor.out","w",stdout);
scanf("%lld%lld%lld%lld%lld",&a,&b,&k,&n,&m);
c[1][0]=c[1][1]=1;a%=mod;b%=mod;
int ans=1;
ans*=(pow(a,n)*pow(b,m))%mod;
if(n>m)n=m;
ans*=dfs(k,n)%mod;ans%=mod;
/*for(int i=1;i<=k;++i){
for(int j=0;j<=i;++j)
printf("%d ",c[i][j]);
printf("\n");
}*/
printf("%lld",ans);
return 0;
}