D. The Number of Pairs_质因数分解gcd

D. The Number of Pairs_gcd质因数分解

题目大意:

给定c,d,x。现在要找出a,b的所有可能性使得下述式子成立

c⋅lcm(a,b)−d⋅gcd(a,b)=xc⋅lcm(a,b)−d⋅gcd(a,b)=x

思路和代码:

首先化简一下原式。

设a=g*A,B=g*b

所以gcd=g,lcm=ABg 。

将其代回原式,得到:ABgc-dg=x,即g(ABc-d)=x。

于是我们只要枚举(ABc-d)即可得到AB的因数。

设i=ABc-d,i一定是x的一个因数(可能是1)。

那么AB=(i+d)/c。我们去分解(i+d)/c的因数就可以得到AB的因数

再考虑如何计算AB的种数。由于AB互质,一种质因子要么给A要么给B。所以我们在分解的时候只要记录质因子即可。

那么问题就变成了有k个质因子,要分给AB两个人,有几种分法。

那么就是C(k,1)+C(k,2)+...+C(k,k)=1<<k

这样就解决了问题,考虑一下时间复杂度比较大,做一个记忆化即可

ll c , d , x ;

int minp[N] ;

int mp[N] ;

void init(){
	for(int i = 2 ; i * i <= 2e7 + 5 ; i ++ )
	if(!minp[i]){
		for(int j = i ; j <= 2e7 + 5 ; j += i)
			if(!minp[j]) minp[j] = i ;
	}
	for(int i = 101 ; i <= 2e7 + 5 ; i ++ )
		if(!minp[i]) minp[i] = i ;//注意大质数不会被筛
}

int cal(ll u){
	if(mp[u]) return mp[u] ;
	ll v = u ;
	int res = 0 ;
	
	while(u > 1){
//		cout << u << "\n" ;
		ll p = minp[u] ;
		while(u % p == 0) u /= p ;
		res ++ ;
	}
	return mp[v] = u > 1 ? res + 1 : res ;
}

void solve(){
	cin >> c >> d >> x ;
	ll ans = 0 ;
	for(int i = 1 ; i <= x / i ; i ++ ){
		if(x % i) continue ;
		ll j = x / i ;
		if((i + d) % c == 0)ans += 1LL << cal((i + d) / c) ;
		if(i != j && (j + d) % c == 0)ans += 1LL << cal((j + d) / c) ;//过滤完全平方数
	}
	cout << ans << "\n" ;
}//code_by_tyrii 

int main(){
	ios::sync_with_stdio(false) ;
	cin.tie(0) ; cout.tie(0) ;
//	freopen("in.in" , "r" , stdin) ;
	init() ;
	
	ll T ; cin >> T ;
	while(T -- )
	solve() ;
	
}

小结:

数学题多推公式

gcd(a,b)可以设A=ag,B=bg。

要注意时间复杂度

posted @ 2022-04-27 14:01  tyrii  阅读(43)  评论(0)    收藏  举报