题意:
已知:
其中n是一个没有重复质因子的数,而φ(x)就是欧拉函数。
求解ans的值。
思路:
首先要知道欧拉函数的公式:
其中,p1到pn是x不重复的质因子。
根据这个公式以及定义,很容易能推导出欧拉函数的几个性质:
有了这些准备就可以求k了,假设p是n的其中一个质因子,将i分成两个部分,i%p!=0和i%p=0,那么就可以进行如下推导:
关于上式中最后一步的推导,i mod p = 0和 i mod p != 0 正好就能构成1到m的所有情况,而后一项中i/p如果看成一个整体i,就可以将范围改成[1,m/p]。
如果我们假设:
那么推导出来的公式就可以化成以下形式:
这样就有了递推关系,可以写一个递归函数来求f(n,m),最多枚举了n中所有质因子p,说明这个递归可以终止。事实上n=1或者m=0时就可以退出。
求出了k,还有需要求ans,这里无限的指数需要利用指数循环节来处理,有如下公式:
根据这个公式也可以写一个递归函数来计算ans的值,因为只要x!=1,φ(x)<x,所以最后一定会递归到C=1的情况,任何数mod1都为0,这时候就可以终止递归。
有了上述推导,代码不难写出。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e7 + 10;
const ll MOD = 1000000007;
ll phisum[MAXN], phi[MAXN], prime[MAXN];
bool vis[MAXN];
void getEuler(int n) {
phi[1] = 1;
int cnt = 0;
for (int i = 2; i <= n; i++) {
if (!vis[i]) {
prime[++cnt] = i;
phi[i] = i - 1;
}
for (int j = 1; j <= cnt; j++) {
if (i * prime[j] > n) break;
vis[i * prime[j]] = 1;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
for (int i = 1; i <= n; i++)
phisum[i] = (phisum[i - 1] + phi[i]) % MOD;
}
int factor[25];
void getfactor(int x) {
int cnt = 0;
for (int i = 2; i <= x; i++) {
if (x % i == 0) {
factor[++cnt] = i;
while (x % i == 0) x /= i;
}
}
if (x > 1) factor[++cnt] = x;
}
ll f(int pos, ll n, ll m) {
if (n == 1) return phisum[m];
if (m == 0) return 0;
int p = factor[pos];
return (phi[p] * f(pos + 1, n / p, m) % MOD + f(pos, n, m / p)) % MOD;
}
ll powmod(ll a, ll n, ll mod) {
ll res = 1;
while (n) {
if (n & 1) res = res * a % mod;
a = a * a % mod;
n >>= 1;
}
return res;
}
ll cal(ll k, int p) {
if (p == 1) return 0;
ll tmp = cal(k, phi[p]) + phi[p];
return powmod(k, tmp, p);
}
int main() {
getEuler(10000000);
int n, m, p;
while (scanf("%d%d%d", &n, &m, &p) == 3) {
getfactor(n);
ll k = f(1, n, m);
ll ans = cal(k, p);
printf("%I64d\n", ans);
}
return 0;
}