Pagini recente » Cod sursa (job #2356177) | Cod sursa (job #1264910) | Cod sursa (job #2756406) | Cod sursa (job #4716) | Cod sursa (job #3166315)
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#ifndef LOCAL
ifstream in("pinex.in");
ofstream out("pinex.out");
#define cin in
#define cout out
#endif
int64_t sum = 0, a;
void bkt(vector<int64_t>& factori_primi, int poz, int64_t sign, int64_t prod) {
if(poz == factori_primi.size()) {
sum += sign * (a / prod);
return;
}
bkt(factori_primi, poz + 1, sign, prod); // nu am ales sa il includ pe factori_primi[poz]
bkt(factori_primi, poz + 1, -1 * sign, prod * factori_primi[poz]); // am ales sa il includ pe factori_primi[poz]
}
void solve() {
int64_t b; cin >> a >> b;
// trebuie sa il factorizam pe b
vector<int64_t> factori_primi;
for(int64_t div = 2; div * div <= b; div++) {
if(b % div == 0) {
// div divide b -> div este un alt factor prim
factori_primi.push_back(div);
}
// il reducem pe div din b
while(b % div == 0) {
b /= div;
}
}
// ne mai ramane cazul cand b > 1, deci si el acum este un propriu factor prim
if(b > 1) {
factori_primi.push_back(b);
b = 1;
}
assert(factori_primi.size() <= 12); // stim asta din constructia 2 * 3 * 5 * .... * 31
// acum trebuie pentru fiecare subset al vectorului factori_primi sa vedem
// 1. cate elemente are -> coeficientul de +-1
// 2. produsul elementelor -> A / (d1 * d2 * ... * dk)
// Varianta 1 -> O(2^N * N)
sum = 0;
/* for(int mask = 1; mask < (1 << factori_primi.size()); mask++) {
int64_t sign = -1, prod = 1;
for(int i = 0; i < factori_primi.size(); i++) {
int ales = (mask >> i) & 1; // am ales sau nu factorul prim d[i] in subsetul nostru curent?
if(ales) {
sign *= -1;
prod *= factori_primi[i];
}
}
sum += sign * (a / prod);
} */
// Varianta 2 -> Backtracking
bkt(factori_primi, 0, 1, 1);
cout << sum << '\n';
return;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int t; cin >> t;
for(int test = 1; test <= t; test++) {
solve();
}
}