大致题意:计算和式
显然是一个道反演的题目,话不多说直接开始推导吧。首先把式子拆成两个求和部分:
然后你会发现前后两个式子都是的形式,于是我们考虑这个式子怎么计算。
如此,你会发现,对于一个固定的a,我们可以在的时间内算出来。因此,对于和式的第二部分,我们可以在的时间内求出来。现在,我们考虑前面那个部分怎么求
然后我们发现,由于y是一个分式而且是向下取整,所以显然我们可以用数论分块一次求一个区间的值。因此在预处理 和 的情况下,我们可以在的时间复杂度内求出答案。这样总的时间复杂度就是预处理时的复杂度,单次询问复杂度为。最后记得要使用__int128保存输入,具体见代码:
#include <bits/stdc++.h>
#define LL long long
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define file(x) freopen(#x".in","w",stdout);
#define bug(x) cerr<<#x<<": "<<x<<endl
using namespace std;
using std::default_random_engine;
const int N = 1e7 + 10;
const int mod = 998244353;
int phi[N],phisum[N],q[N],p[N],sz;
bool isp[N];
typedef __int128 int128;
void init()
{
int sz=0;
phi[1]=1;
for(int i=2;i<N;i++)
{
if(!isp[i])p[++sz]=i,phi[i]=i-1;
for(int j=1;j<=sz&&(LL)i*p[j]<N;j++)
{
isp[i*p[j]]=1;
if(i%p[j]==0)
{
phi[p[j]*i]=phi[i]*p[j];
break;
} else phi[p[j]*i]=(p[j]-1)*phi[i];
}
}
for(int i=1;i<N;i++)
{
phisum[i]=(phisum[i-1]+phi[i])%mod;
q[i]=(q[i-1]+(LL)phi[i]*i%mod)%mod;
}
}
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;
}
int128 getnn(int128 nn)
{
int128 l=0,r=1e9,mid,res;
while(l<=r)
{
mid=(l+r)>>1;
if ((int128)mid*mid*mid<=nn) res=mid,l=mid+1;
else r=mid-1;
}
return res;
}
struct Istream {
template <class T>
Istream &operator >>(T &x) {
static char ch;static bool neg;
for(ch=neg=0;ch<'0' || '9'<ch;neg|=ch=='-',ch=getchar());
for(x=0;'0'<=ch && ch<='9';(x*=10)+=ch-'0',ch=getchar());
x=neg?-x:x;
return *this;
}
}fin;
struct Ostream {
template <class T>
Ostream &operator <<(T x) {
x<0 && (putchar('-'),x=-x);
static char stack[233];static int top;
for(top=0;x;stack[++top]=x%10+'0',x/=10);
for(top==0 && (stack[top=1]='0');top;putchar(stack[top--]));
return *this;
}
Ostream &operator <<(char ch) {
putchar(ch);
return *this;
}
}fout;
int main()
{
init();
LL inv2=qpow(2,mod-2);
int T_T; fin>>T_T;
while(T_T--)
{
int128 n,m,nn;
int t,ans=0;
fin>>n; nn=getnn(n); m=nn*nn*nn;
for(int i=1;i*i<=nn;i++)
{
if (nn%i) continue;
ans=(ans+(n/i-(m-1)/i)%mod*phi[i]%mod)%mod;
if (i*i!=nn)
t=nn/i,ans=(ans+(n/t-(m-1)/t)%mod*phi[t]%mod)%mod;
}
--nn;
for(int l=1,r;l<=nn;l=r+1)
{
t=nn/l; r=nn/t;
LL tmp1=(q[r]-q[l-1]+mod)%mod;
LL tmp2=(phisum[r]-phisum[l-1]+mod)%mod;
ans=(ans+tmp1*inv2%mod*t%mod*(t+1)%mod*(2*t+1)%mod)%mod;
ans=((ans+tmp2*(t+1)%mod*t%mod*inv2%mod*3%mod)%mod+t*tmp2%mod)%mod;
}
assert(ans>=0);
fout<<ans<<'\n';
}
return 0;
}