AT_ABC414_E题解
前言
- 写于2025.7.13
- 题目链接
正文
容易发现一些性质
- n>=a>b>c>=1
- b不整除a
注意:以下为了可读性,都没有取模
暴力代码1
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;
int ans=0;
for(int i=1;i<=n;i++) ans+=n-i-n/i+1;
cout<<ans<<"\n";
return 0;
}
但此时复杂度过高,一定不可以AC,考虑优化,首先把n-i-n/i+1拆开,方便优化
暴力代码2
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;
int ans=0;
for(int i=1;i<=n;i++) ans+=n;
for(int i=1;i<=n;i++) ans-=i;
for(int i=1;i<=n;i++) ans-=n/i;
for(int i=1;i<=n;i++) ans++;
cout<<ans<<"\n";
return 0;
}
观察可以发现,第1,2,4个for循环,显然可以优化
暴力代码3
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;
int ans=0;
ans+=n*n;
ans-=n*(n+1)/2;
for(int i=1;i<=n;i++) ans-=n/i;//A处
ans+=n;
cout<<ans<<"\n";
return 0;
}
只有A处复杂度过高
注意到n<=1e12,可以联想到根号做法
注意到循环的形式,可以很轻松的联想到一个著名的算法---整数分块
用整数分块优化复杂度,即可AC
十分抽象的AC代码
#include<bits/stdc++.h>
#define int long long
#define Int __int128
using namespace std;
const int N=5e5+10,mod=998244353;
signed main(){
int n;cin>>n;
Int ans=(n%mod)*(n%mod)%mod-n%mod*((n+1)%mod)/2;//Int ans=n*n-n*(n+1)/2; ans%=mod;
ans+=n; ans%=mod;
// for(int i=1;i<=n;i++){
// ans-=n/i;
// ans%=mod;
// }
Int res=0;
for(int l=1,r;l<=n;l=r+1){
r=n/(n/l);
res+=(r-l+1)%mod*(n/l)%mod;
res%=mod;
}
ans-=res;
ans=(ans%mod+mod)%mod;
cout<<(int)ans<<"\n";
return 0;
}
//n>=a>b>c>=1
//b!|a

浙公网安备 33010602011771号