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。
要注意时间复杂度

浙公网安备 33010602011771号