贪心+快速幂+思维C. Division
题目大意
给定p和q,求一个最大的x,使得x能整除p且不能被q整除。
解题思路
特判:若p
不能被q
整除(q
不是p
的因子),直接输出p
,即为满足条件的x。
否则q
一定是p
的因子,那么这样的话有什么特点呢?
p
和q
一定都可以被分解成很多的质因子,而对于每一个质因子i
来说,p
中i
的数目一定大于等于q
中i
的数目(否则不能整除了)。
因此,实际上就是把q
中某个质因子拿掉一个,设拿掉之后数目为cnt
,让p
中这个质因子的数目变成cnt
,得到x
,那么就满足x
是p
的因子(因为只是拿掉了部分的质因子)且不能被q
整除(因为某个质因子的数目变少了)。
那么为了找到最大的x
,就对q
的质因子一个个枚举即可,每次只拿掉一个质因子,更新答案。
其实直接从2开始逐个枚举q
的因子也是一样的。
参考代码
我做的还有点复杂,专门统计了q
的质因子个数。之后计算的时候用到了快速幂。
#include<bits/stdc++.h>
using namespace std;
#define LOCAL //提交的时候一定注释
#define _for(i, a, b) for(int i = (a); i < (b); ++i)
#define _rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define pb push_back
#define VI vector<int>
#define maxn 100000
#define INF 0x3f3f3f3f
typedef long long LL;
typedef double db;
const double eps = 1e-6; //定义浮点数误差
struct factor{
int x, cnt;
}fac[20];
int readint(){
int x; scanf("%d", &x); return x;
}
int notPrime[maxn];
LL prime[maxn];
int getP() {
int primeN = 0;
_for(i, 2, maxn) {
if (!notPrime[i]) {
prime[primeN++] = i;
for(int j = i + i; j < maxn; j += i) {
notPrime[j] = 1;
}
}
}
return primeN;
}
int quick(int a, int b) {
//快速幂
int res = 1;
while (b) {
if (b & 1) res = res * a;
a *= a;
b >>= 1;
}
return res;
}
int main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int primeN = getP();
//_for(i, 0, maxN) printf("%d", prime[i]);
int t;
LL p, q;
scanf("%d", &t);
while (t--) {
scanf("%lld%lld", &p, &q);
_for(i, 0, 20) {
fac[i].cnt = 0;}
int num = 0;
//求q的所有质因子及对应的数目
LL tmp = q;
for(int i = 0; i < primeN && prime[i] <= (int)sqrt(1.0*tmp); i++) {
if (tmp % prime[i] == 0) {
fac[num].x = prime[i];
fac[num].cnt = 0;
while (tmp % prime[i] == 0) {
fac[num].cnt++;
tmp /= prime[i];
}
num++;
}
if (tmp == 1) break;
//printf("%d\n", prime[i]);
}
if (tmp != 1) {
fac[num].x = tmp;
fac[num++].cnt = 1;
}
LL ans = -1;
if (p % q) printf("%lld\n", p); //特判,直接输出
else {
_for(i, 0, num) {
LL t = p;
while (t % fac[i].x == 0) {
t /= fac[i].x;
}
ans = max(ans, t * quick(fac[i].x, fac[i].cnt - 1)); //p先把原来的该质因子都除掉,只留下q中数目-1,保证不能被q整除
}
printf("%lld\n", ans);
}
}
return 0;
}