仔细观察这个式子,我们发现如果每次转移到
x
x
x的因数,会多乘一个
c
c
c,为了使答案更大,可以通过每次消掉
x
x
x的一个质因子,那么问题就变成了求
x
x
x的质因数个数,如果我们对每个
x
x
x质因数分解,时间复杂度为
O
(
n
∗
n
)
O(n*\sqrt{n})
O(n∗n),这样会超时,那么可以使用Pollard Rho质因数分解,时间复杂度
O
(
n
∗
n
1
4
)
O(n*n^{\frac{1}{4}})
O(n∗n41)
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define lowbit(x) (x&(-x))
#define mkp(x,y) make_pair(x,y)
#define mem(a,x) memset(a,x,sizeof a);
typedef long long LL;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<double,double> pdd;
const double eps=1e-8;
const double pi=acos(-1.0);
const int inf=0x3f3f3f3f;
const double dinf=1e300;
const LL INF=1e18;
const int Mod=1e9+7;
const int maxn=2e5+10;
LL qkp(LL x,LL n,LL p){
LL ans=1;
while(n){
if(n&1) ans=ans*x%p;
x=x*x%p;
n>>=1;
}
return ans;
}
struct BigIntegerFactor{
const static int maxm = 1e6+16;
LL prime[maxm],p[maxm],fac[maxm],sz,cnt; //多组输入注意初始化cnt = 0
inline LL mul(LL a,LL b,LL mod){ //WA了尝试改为__int128或慢速乘
if(mod <= 1000000000) return a * b % mod;
return (a*b-(LL)((long double)a/mod*b+1e-8)*mod+mod)%mod;
}
void init(int maxn){ //传入的参数不超过maxm,此题需要1e6
int tot = 0; sz = maxn-1;
for(int i = 1;i <= sz; ++i) p[i] = i;
for(int i = 2;i <= sz; ++i){
if(p[i] == i) prime[tot++] = i;
for(int j = 0;j<tot&&1ll*i*prime[j]<=sz; ++j){
p[i*prime[j]] = prime[j];
if(i%prime[j] == 0) break;
}
}
}
LL powl(LL a,LL x,LL mod){
LL res = 1LL;
while(x){
if(x&1) res = mul(res,a,mod);
a = mul(a,a,mod);
x >>= 1;
}
return res;
}
bool check(LL a,LL n){ //二次探测原理检验n
LL t = 0,u = n-1;
while(!(u&1)) t++,u >>= 1;
LL x = powl(a,u,n),xx = 0;
while(t--){
xx = mul(x,x,n);
if(xx==1 && x!=1 && x!=n-1) return false;
x = xx;
}
return xx == 1;
}
bool miller(LL n,int k){ //一般k取20即可
if(n == 2) return true;
if(n < 2 || !(n&1)) return false;
if(n <= sz) return p[n] == n;
for(int i = 0;i <= k; ++i){ //测试k次
if(!check(rand()%(n-1)+1,n)) return false;
}
return true;
}
inline LL gcd(LL a,LL b){
return b == 0 ? a : gcd(b,a%b);
}
inline LL Abs(LL x){
return x < 0 ? -x : x;
}
LL Pollard_rho(LL n){ //基于路径倍增的Pollard_Rho算法
LL s = 0,t = 0,c = rand()%(n-1)+1,v = 1,ed = 1;
while(1){
for(int i = 1; i <= ed; ++i){
t = (mul(t,t,n) + c) % n; v = mul(v,Abs(t-s),n);
if(i % 127 == 0){
LL d = gcd(v,n);
if(d > 1) return d;
}
}
LL d = gcd(v,n); if(d > 1) return d;
s = t; v = 1; ed <<= 1;
}
}
void getfactor(LL n){ //得到所有的质因子(可能有重复的)
if(n <= sz){
while(n != 1) fac[cnt++] = p[n],n /= p[n];
return;
}
if(miller(n,6)) fac[cnt++] = n;
else{
LL d = n; while(d >= n) d = Pollard_rho(n);
getfactor(d); getfactor(n/d);
}
}
LL solve(LL x){ //处理重复质因数
map<LL,LL> mp;
cnt = 0; getfactor(x);
LL ans=0;
for(int i = 0;i < cnt; ++i)
mp[fac[i]]++;
for(auto i: mp) ans+=i.se;
return ans;
}
}Q;
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
//ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
LL c,x,t;
Q.init(1000000);
scanf("%lld",&t);
while(t--){
scanf("%lld%lld",&x,&c);
printf("%lld\n",qkp(c,Q.solve(x),Mod));
}
return 0;
}