Function
本题大佬们都是用线性过的,蒟蒻用nlogn苟过去
题意
求
分析
显然可以分块,
易知,原式为
又因为,所以易知可以以n为周期转移
所以我们可以以n为模块转移
求法
枚举GCD
统计的个数,发现其个数为
因为x为N的因数,gcd(i,N)=x,i应与互质
LL SumGcd(int n,BL k) {
LL Ans=(k/n)*ans[n]%mod;
k=k%n;
if(!k)return Ans;
LL r;
for(int l=1; l*l<=n; l++) {
r=n/(n/l);
if(n%l==0) {
Ans=(Ans+phi[l]*(k/l))%mod;
if(l*l<n)Ans=(Ans+phi[n/l]*(k/(n/l)))%mod;
}
l=r;
}
return Ans;
}
欧拉函数是非完全积性函数,积性函数的约数和也是积性函数
若a为质数,b mod a=0,phi[a*b]=phi[b]*a
以下代码对1-maxn对分解质因数,对1-maxn求
void GetSum() {
for (int i = 1; i <= maxn; i++)ans[i] = 1, num[i] = i;
int g, m, n, p;
for (int i = 0; prime[i]*prime[i]<=maxn; i++) {
p = prime[i];
for (int j = p; j <= maxn; j += p) {
g = 0;
m = n = num[j];
while (n % p == 0) {
n /= p;
g++;
}
ans[j] = ans[j] * (m / n / p * g * (p - 1) + m / n) % mod;
num[j] = n;
}
}
for (int i = 1; i <= maxn; i++)
if (num[i] > 1)
ans[i] = ans[i] * (2 * num[i] - 1) % mod;
LL s = 3;
for (int i = 1; i <= maxn; i++) {
s += 3;
sum[i] =(sum[i-1]+i+ s * ans[i] % mod)%mod;
}
}
代码
#include <iostream>
#include <cstdio>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef __int128 BL;
const int maxn = 10000005;
const LL mod = 998244353;
bool vis[maxn + 5];
int prime[maxn + 5], cnt,phi[maxn];
void Phi() {
phi[1] = 1;
vis[1] = true;
for (int i = 2; i <= maxn; i++) {
if (!vis[i]) prime[cnt++] = i, phi[i] = i - 1;
for (int j = 0; j < cnt && prime[j] * i <= maxn; j++) {
vis[prime[j] * i] = 1;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
int num[maxn + 5];
LL ans[maxn + 5], sum[maxn + 5];
void GetSum() {
for (int i = 1; i <= maxn; i++)ans[i] = 1, num[i] = i;
int g, m, n, p;
for (int i = 0; prime[i]*prime[i]<=maxn; i++) {
p = prime[i];
for (int j = p; j <= maxn; j += p) {
g = 0;
m = n = num[j];
while (n % p == 0) {
n /= p;
g++;
}
ans[j] = ans[j] * (m / n / p * g * (p - 1) + m / n) % mod;
num[j] = n;
}
}
for (int i = 1; i <= maxn; i++)
if (num[i] > 1)
ans[i] = ans[i] * (2 * num[i] - 1) % mod;
LL s = 3;
for (int i = 1; i <= maxn; i++) {
s += 3;
sum[i] =(sum[i-1]+i+ s * ans[i] % mod)%mod;
}
}
BL read() {
BL ret = 0, f = 1;
char ch = getchar();
while (ch<'0' || ch > '9') {
if (ch == '-')
f = -f;
ch = getchar();
}
while (ch >= '0'&&ch <= '9') {
ret = ret * 10 + ch - '0';
ch = getchar();
}
return ret *= f;
}
LL SumGcd(int n,BL k) {
LL Ans=(k/n)*ans[n]%mod;
k=k%n;
if(!k)return Ans;
LL r;
for(int l=1; l*l<=n; l++) {
r=n/(n/l);
if(n%l==0) {
Ans=(Ans+phi[l]*(k/l))%mod;
if(l*l<n)Ans=(Ans+phi[n/l]*(k/(n/l)))%mod;
}
l=r;
}
return Ans;
}
LL res[30];
int main() {
Phi();
GetSum();
int t;
scanf("%d",&t);
while(t--) {
BL n=read();
int l=1,r=maxn,mid,p;
while(l<=r) {
mid=(l+r)/2;
if(n>BL(mid)*mid*mid-1) {
p=mid;
l=mid+1;
} else r=mid-1;
}
LL Ans=sum[p-1];
LL k=n-BL(p)*p*p+1;
if(k==0) {
printf("%lld\n",Ans);
} else {
k--;
Ans+=p;
if(k==0) {
printf("%lld\n",Ans);
} else {
LL res=(Ans+SumGcd(p,k%p)+(k/p)*ans[p])%mod;
printf("%lld\n",res);
}
}
}
}