Problem 1. eqution
Input file: eqution.in
Output file: eqution.out
Time limit: 1 second
Memory limit: 256 MB
Hfu 又来让你帮忙解方程了。
方程是这样的:
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
12
3 13
eqution.out
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
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
bool isprime( int x ){
for( int i = 2; i*i <= x; i++ )
if( x % i == 0 ) return false;
return true;
}
void exgcd( ll a, ll b, ll &d, ll &x, ll &y ){
if( b == 0 ){
x = 1;y = 0;d = a;return ;
} else{
ll x1,y1;
exgcd( b, a%b, d, x1, y1 );
x = y1;
y = x1-(a/b)*y1;
}
}
ll inverse( ll a, ll mod ){
ll d,x,y;
exgcd( a, mod, d, x, y );
if( d < 0 ) d = -d; x = -x; y = -y;
return ( x % mod + mod ) % mod;
}
ll comb( int n, int m, int p ) {
ll rt = 1;
for( int i = 1; i <= m; i++ ) {
rt = rt * (n + 1 - i) % p;
rt = rt * inverse( i, p ) % p;
}
return rt;
}
void merge( ll a1, ll m1, ll a2, ll m2, ll &a, ll &m ){
ll t1,t2,d;
exgcd( m1, -m2, d, t1, t2 );
t1 = (t1 % m2 + m2) % m2;
t1 = t1 * (a2 - a1) / d;
m = m1 * m2;
a = a1 + (m1 * t1) % m;
a = (a % m + m) % m;
}
int main(){
freopen("equation.in","r",stdin);
freopen("equation.out","w",stdout);
int T;
scanf("%d", &T);
while(T--){
int n, m, mod;
scanf("%d%d%d", &n, &m, &mod );
if( isprime(mod) ){
printf("%I64d\n",comb( n+m-1, m, mod ));
}else{
int p,q;
for( int i = 2; i * i <= mod; i++ )
if( mod % i == 0 ){
p = i; q = mod/p; break;
}
ll a1 = comb( n + m - 1, m, p );
ll a2 = comb( n + m - 1, m, q );
ll a,m;
merge( a1, p, a2, q, a, m );
printf("%I64d\n", a);
}
}
return 0;
}