方法1

类比除法分块,打表1 -- 1e6,直接用sum解决。可解决n范围为1到1e12的数据。

#include<cstdio>
#include<iostream>
#include<cmath>
#define int long long
using namespace std;
const int MAXN=2e6;
int a[MAXN],sum[MAXN];
void init(){
	a[1]=3;
	for(int i=2;i<=1000000;i++){
		a[i]=((i+1)*(i+1)-1-(i*i-1))*i;
	}
	for(int i=1;i<=1000000;i++){
		sum[i]=sum[i-1]+a[i];
	}
}

int solve(int n){
	int tmp=sqrt(n);
	int val1=sum[tmp-1];
	int val2=(n-tmp*tmp+1)*tmp;
	return val1+val2;
}

signed main(){
	init();
	int t;
	scanf("%lld",&t);
	while(t--){
		int n;
		scanf("%lld",&n);
		printf("%lld\n",solve(n));
	}
	return 0;
}

方法2

从方法1了解到a[i]=((i+1)*(i+1)-1-(i*i-1))*i,而sum数组是a[i]的前缀和。那么,能否用数学方法优化这个式子呢?

答案是可以的。

#include<cstdio>
#include<iostream>
#include<cmath>
#define int long long
using namespace std;
int solve(int ttmp){
	int n=sqrt(ttmp)-1;
	int val1=n*(n+1)*(2*n+1)/3+n*(n+1)/2;
	n=ttmp;
	int tmp=sqrt(ttmp);
	int val2=(n-tmp*tmp+1)*tmp;
	return val1+val2;
}
signed main(){
	int t;
	scanf("%lld",&t);
	while(t--){
		int n;
		scanf("%lld",&n);
		printf("%lld\n",solve(n));
	}
	return 0;
}