Chino with Equation (隔板法+除法取模)
作者:互联网
链接:
https://ac.nowcoder.com/acm/contest/553/D
Chino的数学很差,因此Cocoa非常担心。今天,Cocoa要教Chino解不定方程。
众所周知,不定方程的解有0个或者若干个。
给出方程:
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(个)。
还有一个问题就是:取模。
因为涉及到除法取模需要用到费马小定理+逆元
①对于正整数和,如果有,那么把这个同余方程中的最小正整数解叫做模的逆元。
②这个为费马小定理,m为素数是费马小定理的前置条件。
求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;
}
标签:取模,正整数,隔板,ll,个数,Chino,Equation,mod 来源: https://blog.csdn.net/Sclong0218/article/details/89101170