题目链接:https://nanti.jisuanke.com/t/38226
sum可以分块求,F(T)和T*T*T放到一起计算前缀和就可以了。
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define ll long long
using namespace std;
const int N = 1e7+1000;
const int mod = 1073741824;
int sum[N];
int prime[N];
bool mark[N];
int F[N],phi[N],T[N];
int tot;
int Low[N];
void get_list(int n){
mark[1] = 1;
Low[1] = 1;
phi[1] = 1;
F[1] = phi[1];
for(int i = 2;i <= n;i ++){
if(!mark[i]) {
Low[i] = i;
prime[++tot] = i;
phi[i] = i-1;
F[i] = phi[i]-phi[1];
}
for(int j = 1;j<=tot&&prime[j]*i<=n;j ++){
mark[i*prime[j]] = 1;
if(!(i%prime[j])) {
Low[i*prime[j]] = Low[i]*prime[j];
if(Low[i]==i) {
phi[i*prime[j]] = prime[j]*phi[i];
F[i*prime[j]] = phi[i*prime[j]]-phi[i];
}
else {
phi[i*prime[j]] = phi[i/Low[i]]*phi[Low[i]*prime[j]];
F[i*prime[j]] = F[i/Low[i]]*F[Low[i]*prime[j]];
}
break;
}
Low[i*prime[j]] = prime[j];
phi[i*prime[j]] = phi[i]*phi[prime[j]];
F[i*prime[j]] = F[i]*F[prime[j]];
}
}
rep(i, 1, n) F[i] = 1ll*F[i]*i%mod*i%mod*i%mod;
rep(i, 1, n) F[i] = (1ll*F[i]+F[i-1])%mod;
}
void init(int n) {
rep(i, 1, n) {
F[i] = (F[i-1]+1)%mod; //第一次提交MLE了,所以只能暂时用F当sum0,phi当sum1,T当sum2
phi[i] = (phi[i-1]+i)%mod; //一开始的做法并没有sum,而是有sum012这三个数组
T[i] = (T[i-1]+1ll*i*i%mod)%mod; //后来发现空间刚好爆,少开一个数组就A了。
}
rep(i, 1, n) {
sum[i] = 1ll*F[i]*phi[i]%mod*T[i]%mod;
F[i] = 0;
phi[i] = 0;
T[i] = 0;
}
}
int main() {
//freopen("a.txt","r",stdin);
init(1e7);
get_list(1e7);
int T;
scanf("%d",&T);
while(T--) {
int n;
scanf("%d",&n);
ll ans = 0;
for(ll l=1,r;l<=n;l=r+1) {
r=n/(n/l);
ans = (ans+1ll*sum[n/l]*(F[r]-F[l-1]+mod)%mod)%mod;
}
printf("%lld\n",ans);
}
//cout<<6*sizeof(sum0)/1024;
return 0;
}