Chino with Equation (隔板法+除法取模)

链接:

https://ac.nowcoder.com/acm/contest/553/D

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

img

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

输入描述:

两个正整数m, n

输出描述:

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

输入
4 7
输出
20 120
思路:

①正整数解:相当于 将n个球排成一排,球与球之间形成n-1个空隙,将两个隔板插入这些空隙中(每空至多插一块隔板),规定由隔板分成的m部分的球数分别为x1、x2、x3…xm之值。则隔法与解的个数之间建立了一一对立关系,故解的个数为C(n-1,m-1)=C(6,3)=20(个)。

②非负整数解: 刚才我们求的是正整数解,现在求非负整数的解(也就是可以为0),我们刚才隔板分成的这些部分都不能为0,现在我们可以转换一下

注意到x1、x2、x3…xm可以为零,故例1解法中的限定“每空至多插一块隔板”就不成立了,怎么办呢?只要添加m个球,给x1、x2、x3…xm各添加一个球,**这样原问题就转化为求 x1+x2+x3…+xm=n+m的正整数解的个数了,**则问题就等价于把n+m个相同小球放入m个不同箱子,每个箱子至少一个,有几种情况?易得解的个数为C(n+m-1,m-1)=C(10,3)=120(个)。

还有一个问题就是:取模。

因为涉及到除法取模需要用到费马小定理+逆元

①对于正整数imgimg,如果有img,那么把这个同余方程中img的最小正整数解叫做imgimg的逆元。

②这个为费马小定理,m为素数是费马小定理的前置条件。

img

求a/b=x(mod M)

只要M是一个素数,而且b不是M的倍数,就可以用一个逆元整数b1,通过 a/b=a*b1 (mod M),只能来以乘换除。
费马小定理:对于素数 M 任意不是 M 的倍数的 b,都有:b ^ (M-1) = 1 (mod M)于是可以拆成:b*b^(M-2)=1(mod M)于是:a/b=a/b*(b * b ^ (M-2))=a*(b ^ (M-2)) (mod M),这里不就是用b^(M-2)代替了1/b吗!

综上:(a/b)%m = a / b * (b*b^(m-2)) = (a * (b^(m-2)))%m;

代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll Mod = 1e9+7;
ll qc(ll a,ll b,ll c)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
            ans=(ans*a)%c;
        a=(a*a)%c;
        b>>=1;
         
    }
    return ans;
}
int main()
{
    ll n, m;
    cin >> m >> n;
    ll sum1 = 1;
    ll sum3 = 1;
     
    ll sum2 = 1;
    for(int i = 1; i <=m-1; i++) {
        sum1=(sum1 * (n+m-i))%Mod;
        sum3=(sum3 * (n-i))%Mod;
        sum2=(sum2*i)%Mod;
    }
    printf("%lld %lld\n",(sum3*qc(sum2,Mod-2,Mod))%Mod,sum1*qc(sum2,Mod-2,Mod)%Mod);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值