Problem Description
Input
Output
Sample Input
Sample Output
Source
2020 Multi-University Training Contest 6
得到上式后我们可以对这三项进行预处理
然后我们再进行两次整除分块,求得ans。
#include<bits/stdc++.h>
#define db double
#define ll long long
#define inf 0x3f3f3f3f
#define ms(x,a) memset(x,a,sizeof(x))
using namespace std;
const int maxn = 2e5 + 10;
const ll mod = 1e9 + 7;
const ll mod1 = 1e9 + 6;
ll k,x,n;
ll qpow(ll x,ll n){
ll res = 1;
while(n){
if(n & 1)res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
}
bool v[maxn];
int cnt;
ll p[maxn],mob[maxn],sm[maxn],s1[maxn],s2[maxn];
void getmob(){
ms(v,0);
ms(p,0);
ms(mob,0);
ms(sm,0);
cnt = 0;
mob[1] = v[1] = 1;
for(int i = 2;i < maxn;i++){
if(!v[i]){
p[++cnt] = i;
mob[i] = -1;
}
for(int j = 1;j <= cnt && i * p[j] <= maxn;j++){
v[i * p[j]] = 1;
if(i % p[j] == 0){
mob[i * p[j]] = 0;
break;
}
else{
mob[i * p[j]] = -mob[i];
}
}
}
for(int i = 1;i < maxn;i++){
sm[i] = (sm[i - 1] + qpow(i,k)) % mod;
}
for(int i = 1;i < maxn;i++){
sm[i] = qpow(sm[i],x);
s1[i] = (s1[i - 1] + qpow(i,(x * k + 1) % mod1 + mod1) * mob[i] * mob[i] % mod) % mod;
s2[i] = ((s2[i - 1] + qpow(i,x * k % mod1 + mod1) * mob[i] % mod) % mod + mod) % mod;
}
}
unordered_map<ll,ll>mp;
ll calc1(ll x){
if(mp[x])return mp[x];
ll res = 0;
for(ll l = 1,r;l <= x;l = r + 1){
r = x / (x / l);
res = ((res + (s2[r] - s2[l - 1]) * sm[x / l]) % mod + mod) % mod;
}
return mp[x] = res;
}
ll calc2(ll x){
ll res = 0;
for(ll l = 1,r;l <= x;l = r + 1){
r = x / (x / l);
res = ((res + (s1[r] - s1[l - 1]) * calc1(x / l)) % mod + mod) % mod;
}
return res;
}
void solve(){
scanf("%lld",&n);
printf("%lld\n",calc2(n));
}
int main() {
// ios::sync_with_stdio(false);
// cin.tie(0);
int t;
scanf("%d%lld%lld",&t,&k,&x);
getmob();
for(int ca = 1; ca <= t; ca++) {
solve();
}
return 0;
}
//Dawn_Exile