【noip2011】【数学】计算系数 逆元求组合数

来源:互联网 发布:b2b 知乎 编辑:程序博客网 时间:2024/06/06 02:25

描述

给定一个多项式(ax + by)^k,请求出多项式展开后x^n * y^m项的系数。

输入格式

共一行,包含5个整数,分别为a,b,k,n,m,每两个整数之间用一个空格隔开。

输出格式

输出共1行,包含一个整数,表示所求的系数,这个系数可能很大,输出对10007取模后的结果。

样例输入

1 1 3 1 2

样例输出

3

限制

1s

提示

对于30%的数据,有0 ≤ k ≤ 10;
对于50%的数据,有a = 1, b = 1;
对于100%的数据,有0 ≤ k ≤ 1000,0 ≤ n, m ≤ k,且n+m = k,0 ≤ a,b ≤ 1,000,000.

这个题就是一个组合数或者杨辉三角,公式可以很快退出来Cnk×an×bm

然后我觉得最快的方法是用逆元求组合数,是O(n)的其他方法都是O(n2)虽然都可以过,然后线性求逆元可与去看这篇文章:http://blog.csdn.net/outer_form/article/details/51509360 我就不详细写了

然后这道题代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<set>#include<map>#include<queue>#include<algorithm>#include<vector>#include<cstdlib>#include<cmath>#include<ctime>#include<stack>#define INF 2100000000#define ll long long#define clr(x)  memset(x,0,sizeof(x))#define clrmax(x)  memset(x,127,sizeof(x))using namespace std;#define M 1005#define P 10007ll k,m,n,a,b;ll inv[M];void get_inv(){    inv[1]=1;    for(int i=2;i<=1000;i++)        inv[i]=(P-(P/i))*inv[P%i]%P;}ll mi(ll a,ll b){    if(b==1)return a;    if(b==0)return 1;    ll temp=mi(a,b/2);    return b%2==0?temp*temp%P:temp*temp*a%P;}ll C(ll a,ll b){    ll ret=1;    for(int i=b;i>=b-a+1;i--)        ret=ret*i%P;    for(int i=1;i<=a;i++)        ret=ret*inv[i]%P;    return ret;}int main(){    cin>>a>>b>>k>>n>>m;    get_inv();    cout<<C(n,k)*mi(a,n)%P*mi(b,m)%P;    return 0;}

大概就是这个样子,如果有什么问题,或错误,请在评论区提出,谢谢。

0 0