2019西北工业大学程序设计创新实践基地春季选拔赛(重现赛) D Chino with Equation 逆元

题目描述

Chino的数学很差,因此Cocoa非常担心。今天,Cocoa要教Chino解不定方程。
众所周知,不定方程的解有0个或者若干个。
给出方程:

Cocoa想知道这个不定方程的正整数解和非负整数解各有几个。
题目对Chino来说太难啦,你能帮一帮Chino吗?

输入描述:

两个正整数m, n

输出描述:

题目要求的答案,即正整数解的个数和非负整数解的个数 。由于答案可能会很大,你只需要输出答案 mod(109 + 7) 即可。

示例1

输入

复制

4 7

输出

复制

20 120

思路:

利用挡板思想。

(1)正整数解:

         可以抽象成有n-1个挡板,从中选m-1个,将物品分成m部分,即为C(n-1,m-1);

 (2)  非负整数解:

扫描二维码关注公众号,回复: 6047390 查看本文章

        因为有的划分部分可能为空,所以共有n+m-1个挡板,从中选m-1个,将物品分成m部分,即为C(n+m-1,m-1);

C(n,m)的公式为:n!/(m!*(n-m)!);

分母部分的两个数需要求出逆元,然后直接相乘即为答案。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=2*1e6+5;
ll ji[maxn];
ll m,n;
ll quick(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b%2) ans=ans*a%mod;
        a=a*a%mod;
        b/=2;
    }
    return ans;
}
void solji()
{
    ji[0]=1;
    for (int i=1;i<maxn;i++) {
            ji[i]=ji[i-1]*i%mod;
    }
}
int main()
{
    solji();
    scanf("%lld%lld",&m,&n);
    ll n1=n-1,m1=m-1;
    ll n2=n+m-1,m2=m-1;
    ll inv1=quick(ji[m1],mod-2);
    ll inv2=quick(ji[n1-m1],mod-2);
    ll ans1=ji[n1]*inv1%mod*inv2%mod;
    ll inv3=quick(ji[m2],mod-2);
    ll inv4=quick(ji[n2-m2],mod-2);
    ll ans2=ji[n2]*inv3%mod*inv4%mod;
    printf("%lld %lld\n",ans1,ans2);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/89100892