Problem 1.
Input file: eqution.in
Output file: eqution.out
Time limit: 1 second
Memory limit: 256 MB
Mr. Hu 又来让你帮忙解方程了。
方程是这样的:
x1 + x1 + x3 + + xn = m (xi 0 81 i n)
Mr. Hu 希望你求出这个n 元一次方程的整数解有多少个,因为解的个数有可能变得很大,所以Mr. Hu
只需要你输出解的个数取模于mod。
Input
第1 行,包含一个整数:T,表示询问个数
接下来T 行,每行包含三个整数:n m mod
Output
输出T 行,每行输出解的个数模对应mod
Sample
eqution.in eqution.out
12
3 13
4
Note
样例中,解分别是:(3; 0); (2; 1); (1; 2); (0; 3)
• 对于30% 的数据,1 n;m 6,mod = 108 + 7,T = 1
• 对于70% 的数据,1 n;m 103,n + m mod 108 + 7,mod 是一个素数,1 T 100
• 对于余下30% 的数据,1 n;m 103,n+m p; q 104,mod = pq,p; q 是素数,1 T 103
1.1 30% 数据
暴力,这时答案本身很小,所以只需要写一个dfs。
1.2 70% 数据
这个问题等价于“将m 个相同的球放进n 个不同的盒子中”的方案数,
也可以暴力乘+逆元。
复杂度后者好点(因为模数不同,前者每次都要推一遍)
1.3 余下30% 数据
用公式推应该会超时,只能用后面那个,求逆元可以用扩展欧几里得,也可以
欧拉定理。当然也可以在在模p 和模q 时
答案求出来,再用中国剩余定理合并。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#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 ms(a,x) memset(x,a,sizeof(x))
#ifdef win32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
int t,n,m,mod;
template <class T> void exgcd(T a, T b, T& d, T& x, T& y) {
if(!b) d = a, x = 1, y = 0;
else exgcd(b, a%b, d, y, x), y -= (a/b)*x;
}
template <class T> inline T inv(T a, T n) {
T d,x,y;
exgcd(a, n, d, x, y);
return d == 1 ? ((x+n)%n) : (-1);
}
inline int Comb(int x, int y) {
LL ret = 1, b = 1;
for(int i = y; i > y - x; i--) (ret *= i) %= mod;
for(int i = 2; i <= x; i++) (b *= i) %= mod;
(ret *= inv(b, (LL)mod)) %= mod;
return (int)ret;
}
int main() {
freopen("equation.in","r",stdin);
freopen("equation.out","w",stdout);
scanf("%d",&t);
while(t--) {
scanf("%d%d%d",&n,&m,&mod);
printf("%d\n", Comb(n-1, n+m-1));
}
return 0;
}