HDU 4497 数论+组合数学

时间:2022-01-15 03:17:25

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4497

解题思路:将满足条件的一组x,z,y都除以G,得到x‘,y',z',满足条件gcd(x',y',x') = 1,同时lcm(x',y',x') = G/L.

特判,当G%L != 0 时,无解。

然后素数分解G/L,假设G/L = p1^t1 * p2^t2 *````* pn^tn。

满足上面条件的x,y,z一定为这样的形式。

x' = p1^i1 * p2^i2 *```* pn^in.

y' = p1^j1 * p2^j2 * ```*pn^jn.

z' = p1^k1 * p2^k2 * ```*pn^kn.

为了满足上面的条件,对于p1,一定有max(i1,j1,k1) = t1.min(i1,j1,k1) =0;则当选定第一个数为0,第二个数为t1时,第三个数可以为0-t1,又由于有顺序的,只有

(0,t1,t1) 和(0,t1,0)这两种情形根据顺序只能产生四种结果,其他的由于三个数都不一样,一定能产生6种,所以最后产生了6*(t1-1)+3*2 = 6*t1种,根据乘法原理以及关于素数分解的唯一性,反过来,素数组合必然也是唯一的数,一共有6*t1 * 6*t2 *`````*6*tn种选法。

另一种思考:容斥原理,对于p1,一共有(t1+1)^3种,但是没有最高位t1的选法是不合法的,减去,一共有t1^3种选法不合法,没有最低位0的选法是不合法的,也是t1^3,发现多减了,所以加上多减的既没有最高位也没有最低位的(t1-1)^3,通过化简得6*t1`````

贴代码:

 #include<cstdio>
#include<cmath>
#define N 100005
int a[N],b[N];
void factor(int n,int &tot)
{
int temp,i;
temp =(int)(sqrt(n) +);
tot =-;
for(int i=; i <= temp; ++i)
{
if(n%i == )
{
a[++tot] = i;
b[tot] = ;
while(n%i == )
{
++b[tot];
n /= i;
}
}
}
if(n != )
{
a[++tot] = n;
b[tot] = ;
}
}
int main()
{
// freopen("in.txt","r",stdin);
int t,G,L;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&G,&L);
if(L%G != )
{
printf("0\n");
continue;
}
L = L/G;
int tot;
factor(L,tot);
long long int ans =;
for(int i=; i<=tot; ++i) ans *= (*b[i]);
printf("%I64d\n",ans);
}
return ;
}