/*
某地发行一套彩票。彩票上写有1到M这M个自然数。彩民可以在这M个数中任意选取N个不同的数打圈。每个彩民只能买一张彩票,不同的彩民的彩票上的选择不同。
每次抽奖将抽出两个自然数X和Y。如果某人拿到的彩票上,所选N个自然数的倒数和,恰好等于X/Y,则他将获得一个纪念品。
已知抽奖结果X和Y。现在的问题是,必须准备多少纪念品,才能保证支付所有获奖者的奖品。
输入输出要求
输入文件有且仅有一行,就是用空格分开的四个整数N,M,X,Y。
输出文件有且仅有一行,即所需准备的纪念品数量。
1≤X, Y≤100,1≤N≤10,1≤M≤50。
输入数据保证输出结果不超过105。
输入输出样例
Money.in Money.out
2 4 3 4 1
*/
#include < stdio.h >
#include < string .h >
#include < math.h >
#include < stdlib.h >
#define MAX 101
long total = 0 ;
int m,n,x,y ;
int flag[MAX] = { 0 } ;
int save[MAX] = { 0 } ;
int gcd( int a, int b)
{
if ( b == 0 )
return a ;
else
return gcd(b,a % b) ;
}
int is_same()
{
int fz = 0 ,fm = 0 ;
int i,j,k,maxk,temp;
maxk = gcd(save[ 1 ],save[ 2 ]) ;
fm = (save[ 1 ] * save[ 2 ]) / maxk ;
fz = save[ 1 ] / maxk + save[ 2 ] / maxk ;
save[ 2 ] = fm ;
for (i = 3 ; i <= n ; i ++ )
{
maxk = gcd(save[i - 1 ],save[i]);
fm = (save[i - 1 ] * save[i]) / maxk ;
fz = fz * (save[i - 1 ] / maxk) + save[i] / maxk ;
save[i] = fm ;
}
if (fz == x && fm == y)
return 1 ;
else
return 0 ;
}
void find ( int num)
{
int i,j ;
if ( num > n)
{
if (is_same())
{
total ++ ;
}
test ++ ;
}
else
{
for (i = 1 ; i <= m ; i ++ )
if ( ! flag[i] && i > save[num - 1 ])
{
flag[i] = 1 ;
save[num] = i ;
find (num + 1 );
flag[i] = 0 ;
save[num] = 0 ;
}
}
}
int main( void )
{
int max,h;
scanf( " %d %d %d %d " , & n, & m, & x, & y);
max = gcd(x,y) ; /* 检查它是否为最简式 */
if ( max > 1 ) /* 化为最简式 */
{
x /= max ;
y /= max ;
}
if ( n == 1 ) /* 如果n为1直接处理 */
{
if ( x == 1 )
{
for (h = 1 ; h <= m ; h ++ )
if ( y == h)
total ++ ;
}
}
else
{
find ( 1 );
}
printf( " %ld " ,total);
return 0 ;
}