AT_ABC414_E题解

前言

正文

容易发现一些性质

  • 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
posted @ 2025-07-13 12:33  Ming3398  阅读(22)  评论(0)    收藏  举报