题意:
给一个很大的数c,问是否存在a和b,使得a + b = c且rad(abc) < c;
注:rad(abc)等于abc相乘结果的质因数的乘积
思路:
要满足a + b = c,首先c可以表示成c = A * B * C * D…打表可以看出只要A或B或C或…其中一个有幂次就输出yes,否则就输出no
但是怎么打表呢??? 我待会儿去学一下
其次就是大数质因数分解定理的模板,敲上去,得到c的全部质因子,注意得到的是没有去重过的,而且c不能为1,我们需要把所有的质因子放进set,同时遍历set,将set里面的质因子相乘,最后判断即可
代码实现:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
const int S = 20;
ll cc;
ll factor[maxn];
ll tol = 0;
ll mult_mod(ll a, ll b, ll c){
a = a % c;
b = b % c;
ll ret = 0;
while(b){
if(b & 1){ret += a; ret %= c;}
a <<= 1;
if(a >= c) a = a % c;
b >>= 1;
}
return ret;
}
ll pow_mod(ll x,ll n,ll mod){
if(n == 1) return x % mod;
x = x % mod;
ll tmp = x;
ll ret = 1;
while(n){
if(n & 1) ret = mult_mod(ret,tmp,mod);
tmp = mult_mod(tmp,tmp,mod);
n >>= 1;
}
return ret;
}
bool check(ll a,ll n,ll x,ll t){
ll ret = pow_mod(a,x,n);
ll last = ret;
for(int i = 1;i <= t;i++){
ret = mult_mod(ret,ret,n);
if(ret==1&&last!=1&&last!=n-1) return true;
last = ret;
}
if(ret != 1) return true;
return false;
}
bool Miller_Rabin(ll n){
if(n < 2) return false;
if(n == 2) return true;
if((n & 1) == 0) return false;
ll x = n - 1;
ll t = 0;
while((x & 1) == 0){x >>= 1; t++;}
for(int i = 0;i < S;i++){
ll a = rand() % (n - 1) + 1;
if(check(a,n,x,t)) return false;
}
return true;
}
ll gcd(ll a,ll b){
if(a == 0) return 1;
if(a < 0) return gcd(-a,b);
while(b){
ll t = a % b;
a = b;
b = t;
}
return a;
}
ll Pollard_rho(ll x,ll c){
ll i = 1,k = 2;
ll x0 = rand() % x;
ll y = x0;
while(1){
i++;
x0 = (mult_mod(x0,x0,x)+c)%x;
ll d = gcd(y - x0,x);
if(d != 1&&d != x) return d;
if(y == x0) return x;
if(i == k){y = x0; k += k;}
}
}
void findfac(ll n){
if(Miller_Rabin(n)){
factor[tol++] = n;
return ;
}
ll p = n;
while(p >= n) p = Pollard_rho(p,rand() % (n - 1) + 1);
findfac(p);
findfac(n / p);
}
int main(){
int tt;
scanf("%d",&tt);
while(tt--){
scanf("%lld",&cc);
/*大数分解定理不能对1进行分解*/
if(cc == 1){
printf("no\n");
continue;
}
tol = 0;
findfac(cc);
ll ans = 1;
set<ll> st;
for(int i = 0;i < tol;i++){
st.insert(factor[i]);
}
set<ll>::iterator it;
for(it = st.begin();it != st.end();it++)
ans = ans * (*it);
if(ans < cc) printf("yes\n");
else printf("no\n");
}
return 0;
}