本人思路:
二次数论分块
对于每一个 1≤x≤n ,求满足 1≤y,z≤xn且 yz≤n的个数并求和。
代码的时间复杂度似乎是O(Tnlog(n))的
#include<bits/stdc++.h>
#define MAX 0x3fffffffffffffffL
#define int long long
#define ipairs pair<int,int>
#define endl '\n'
#define mod 998244353
using namespace std;
int solve(int n,int m){
int res=0;
for(int l=1,r;l<=m;l=r+1){
r=min(max(n/(n/l),n/m),m);
res+=(r-l+1)*(min(n/l,m))%mod;
res%=mod;
}
return res;
}
vector<int>b;
int solve_(int n,int m,int t){
if(m*m<=n)return m*m%mod;
int now=n;
int u=2;
int l=0,r=b.size();
while(l+1<r){
int mid=l+((r-l)>>1);//二分
if(n/mid<=m)r=mid;
else l=mid;
}
u=(l+1)*2;
t=b[l];
now=n/(l+1);
for(int i=l+1;;i++){
if(n/i<=m){
return ((t-u*(now-m))%mod+mod)%mod;
}else{
t-=u*(now-n/i);
t=(t%mod+mod)%mod;
now=n/i;
u+=2;
}
} //求solve函数打表找规律
}
int solve2(int n){
int res=0;
int t=solve(n,n);
int tt=t;
int u=2;
int now=n;
for(int i=2;i*i<=n||(i<=n&&i<=10);i++){//防止b.size()=0
b.push_back(tt);
tt-=u*(now-n/i);
tt=(tt%mod+mod)%mod;
now=n/i;
u+=2;
}
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),n);
res+=(r-l+1)*(solve_(n,n/l,t))%mod;
res%=mod;
}
return res;
}
signed main(){
int t;
cin>>t;
while(t--){
b.clear();
int n;
cin>>n;
cout<<solve2(n)<<endl;
}
return 0;
}
结果,只过了样例....
求调