ABC162E (AT5310)
jijidawang · · 题解
UPD on 8.14 更新时间复杂度分析
这里欧拉反演的优势就体现出来了 .
主要就是借助范德蒙德卷积恒等式
接下来对原式进行一些基本操作
然后就是老生常谈的东西了,先整除分块,然后肯定要线性筛欧拉函数 .
此时的时间复杂度是
然而指数一定我们就可以线性筛
然而此时预处理的时间复杂度变成
根据素数定理
于是可以做到
目前是最优解 rk4 .
至少在我发这篇题解的时候是这样,前面仨老哥都是带
可能我代码自带大常数吧 QwQ .
代码:
#include <bits/stdc++.h>
template<typename T>
inline T chkmin(T& x, const T& y){if (x > y) x = y; return x;}
template<typename T>
inline T chkmax(T& x, const T& y){if (x < y) x = y; return x;}
using namespace std;
const int N = 114514, P = 1e9+7;
bool notprime[N];
int n, k, phi[N], power[N];
vector<int> plist;
inline int qpow(int a, int n)
{
int ans = 1;
while (n)
{
if (n & 1) ans = 1ll * ans * a % P;
a = 1ll * a * a % P; n >>= 1;
} return ans;
}
inline void linear_sieve()
{
notprime[1] = true; phi[1] = power[1] = 1;
for (int i=2; i<=k; i++)
{
if (!notprime[i]){plist.emplace_back(i); power[i] = qpow(i, n); phi[i] = i-1;}
for (auto x : plist)
{
int now = i*x;
if (now > k) break;
notprime[now] = true;
if (!(i%x)){phi[now] = phi[i] * x; power[now] = 1ll * power[i] * power[x] % P; break;}
power[now] = 1ll * power[i] * power[x] % P; phi[now] = phi[i] * phi[x];
}
}
for (int i=1; i<=k; i++) phi[i] = (phi[i] + phi[i-1]) % P;
}
int main()
{
scanf("%d%d", &n, &k); linear_sieve();
int ans = 0;
for (int l=1, r; l <= k; l = r+1)
{
r = k / (k / l);
ans = (ans + 1ll * (phi[r] - phi[l-1]) % P * power[k / l] % P) % P;
} printf("%d\n", (ans + P) % P);
return 0;
}