链接:https://ac.nowcoder.com/acm/contest/553/D
来源:牛客网
题目描述
Chino的数学很差,因此Cocoa非常担心。今天,Cocoa要教Chino解不定方程。
众所周知,不定方程的解有0个或者若干个。
给出方程:
Cocoa想知道这个不定方程的正整数解和非负整数解各有几个。
题目对Chino来说太难啦,你能帮一帮Chino吗?
输入描述:
两个正整数m, n
输出描述:
题目要求的答案,即正整数解的个数和非负整数解的个数 。由于答案可能会很大,你只需要输出答案 mod(109 + 7) 即可。
示例1
输入
复制
4 7
输出
复制
20 120
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const long long mod = 1e9+7;
int n,m;
ll mul(ll a,ll b,ll c ){
ll res=0;
// a%=c;
while(b){
if(b&1){
res=(res+a)%c;
}
a=(a+a)%c;
b>>=1;
}
return res;
}
// a^b%c 快速幂+快速乘
ll qc(ll a,ll b,ll c){
ll res=1;
// a%=c;
while(b){
if(b&1){
res = mul(res,a,c);
}
a = mul(a,a,c);
b>>=1;
}
return res;
}
int main(){
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;
}
隔板法
1.
正整数解的个数的情况
隔板法就是在n个元素间插入(m-1)个板,即把n个元素分成b组的方法。
C(n-1,m-1)
隔板法必须满足三个条件:
这n个元素必须相同,(2)所分成的每一组至少分得一个元素,(3)分成的组别彼此差异。
例如:某校组建一球队需16人,该校共10个班级,且每个班至少分配一个名额,共有几种情况。C(16-1,10-1)。
2.
非负整数解
对n件相同物品(或名额)分给m个人(或位置),允许若干个人(或位置)为空的问题,可以看成将这n件物品分成m组,允许若干组为空的问题.将n件物品分成m组,需要m-1块隔板,将这n件物品和m-1块隔板排成一排,占n+m-1位置,从这n+m-1个位置中选m-1个位置放隔板,因隔板无差别,故隔板之间无序,是组合问题,故隔板有**C(n+m-1,m-1)**种不同的方法,再将物品放入其余位置,因物品相同无差别,故物品之间无顺序,是组合问题,只有1种放法,根据分步计数原理,共有
C(n+m-1, m-1×1)=**C(n+m-1,m-1)**种排法
3.
求方程x1+x2+…+xk=n的非负整数解或正整数解
(1)方程x1+x2+x3+x4=10的正整数解有多少组?(m==4的情况)
(2)方程x1+x2+x3+x4=10的非负整数解有多少组?
解:(1)转化为10个相同的小球装入4个不同的盒子,每盒至少有一个,有C(10-1,4-1)=84种。
转化为10个相同的小球装入4个不同的盒子,可以有空盒,有C(10+4-1,4-1)种。
4.求方程x1+x2+…+xm=k(0<=xi<=n)的非负整数解的方案数。
解:有限制条件,用容斥搞一搞。
对于指定t个盒子(例如1,2,3,···,t号盒子)中的球数至少为N+1个球的方法等同于将(X-t*(N+1))个球放入Y个盒中,每个盒中至少0个球的放法,即(X-t*(N+1))个球放入Y个盒子,再在指定的t个盒中放入N个,为C(X-t*(N+1)+Y-1,Y-1)。
根据容斥原理,每个盒子至多N个球的方法为总数-所有指定一个盒子的球数大于N的方法+所有指定两个盒子的球数大于N的方法-所有三个盒子的球数大于N的方法+
即为C(k+m-1,m-1)-C(m,1)C(k-(n+1)+m-1,m-1)+C(m,2)C(k-2(n+1)+m-1,m-1)+···+(-1)^tC(m,t)C(k-t(N+1)+m-1,m-1)+···
其中t属于1到k/(N+1)的闭区间。C(k-t*(N+1)+m-1,m-1)的k-t*(N+1)+m-1>=m-1,一化简就可得到k/(N+1)。
因为涉及到除法取模需要用到费马小定理+逆元
(a/b)%m = a / b * (b*b^(m-2)) = (a * (b^(m-2)))%m;