题意:求l到r中所有数的k次方的因数个数之和。
将i分解质因数,则d(i)等于各个质因数上的指数+1之积。因此d(i^k)等于(i*k+1)之积。l,r<=1e12,因此筛出1e6以内的素数,然后枚举每个素数,再枚举这个素数的每个倍数,将其分解质因数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define ll long long
const int maxn = 1e6 + 10;
const ll MOD = 998244353;
bool isprime[maxn];
ll prime[maxn];
int cnt = 0;
void getprime() // 筛出1e6以内的素数
{
memset(isprime, true, sizeof(isprime));
isprime[0] = isprime[1] = false;
for (ll i = 2; i <= 1000000; i++)
{
if (isprime[i])
{
prime[++cnt] = i;
for (ll j = i * i; j <= 1000000; j += i)
isprime[j] = false;
}
}
}
ll d[maxn];
ll arr[maxn];
ll solve(ll l, ll r, ll k)
{
for (int i = 1; i <= cnt; i++) // 枚举每个素数
{
ll tmp = (l + prime[i] - 1) / prime[i] * prime[i];
while (tmp <= r)
{
ll cnt = 0;
while (arr[tmp - l] % prime[i] == 0)
{
cnt++;
arr[tmp - l] /= prime[i];
}
d[tmp - l] *= (k * cnt + 1);
d[tmp - l] %= MOD;
tmp += prime[i]; // 枚举这个素数的所有倍数
}
}
ll ans = 0;
for (ll i = l; i <= r; i++)
{
if (arr[i - l] == 1) ans += d[i - l];
else ans += d[i - l] * (k + 1);
ans %= MOD;
}
return ans;
}
int main()
{
getprime();
int T;
scanf("%d", &T);
while (T--)
{
ll l, r, k;
scanf("%lld %lld %lld", &l, &r, &k);
for (ll i = l; i <= r; i++)
{
arr[i - l] = i;
d[i - l] = 1;
}
ll ans = solve(l, r, k);
printf("%lld\n", ans);
}
}