所有输入的数都是小于1e5+1的正整数。
分析
10w以内就130个约数不到。
设 g ( d ) g(d) g(d)为是d的倍数的数的个数,然后每次用约数个数的时间暴力维护。
考虑枚举gcd=d,那么问题就变成了gcd(x,y)=d的y的个数。要减去满足d|gcd(x,y)的,这些y必定是d’的倍数,满足d|d’|n。 但注意到直接减会重复,其实相当于做高维差分了。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
int n,g[N],f[N];
int p[N],is[N],mi[N];
void init() {
for (int i = 2; i <= 1e5; i++) {
if (!is[i]) p[++p[0]] = i, mi[i] = i;
for (int j = 1; j <= p[0] && p[j] * i <= 1e5; j++) {
is[i * p[j]] = 1;
mi[i * p[j]] = p[j];
if (i % p[j] == 0) break;
}
}
}
int X,k,mo;
int mc,fac[200],cnt;
pair<int,int> pf[100];
void fj(int x) {
cnt = 0;
while (x != 1) {
int t = mi[x];
pf[++cnt].first = mi[x];
pf[cnt].second = 0;
while (x % t == 0) x /= t, pf[cnt].second++;
}
sort(pf+1,pf+1+cnt);
}
void getfac(int x,int v) {
if (x > cnt) {
fac[++fac[0]] = v;
return;
}
int t = 1;
for (int i = 0; i <= pf[x].second; i++, t *= pf[x].first) {
getfac(x+1, v * t);
}
}
ll ksm(ll x,ll y) {
ll ret = 1; for (; y; y>>=1) {
if (y & 1) ret = ret * x % mo;
x = x * x % mo;
}
return ret;
}
char c;
void read(int &x) {
while ((c=getchar())<'0' || c>'9');
x=c-'0'; while ((c=getchar())>='0' && c<='9') x=x*10+c-'0';
}
int main() {
freopen("a.in","r",stdin);
init();
cin>>n; for (int i = 1; i <= n; i++) {
read(X),read(k),read(mo);
fj(X);
fac[0] = 0, getfac(1,1);
for (int i = 1; i <= fac[0]; i++) {
g[fac[i]]++;
f[fac[i]] = g[fac[i]];
}
for (int j = 1; j <= cnt; j++) {
int w = pf[j].first;
for (int i = 1; i <= fac[0]; i++) {
int y = fac[i]; if (y % w == 0) {
f[y / w] -= f[y];
}
}
}
int ans = 0;
for (int i = 1; i <= fac[0]; i++) {
ans = (ans + ksm(fac[i], k) * f[fac[i]]) % mo;
}
printf("%d\n",ans);
}
}