专栏文章

题解:AT_abc414_e [ABC414E] Count A%B=C

AT_abc414_e题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miowtkq6
此快照首次捕获于
2025/12/03 02:26
3 个月前
此快照最后确认于
2025/12/03 02:26
3 个月前
查看原文

解题思路

由于余数 cca,ba,b 密切相关,且当 a,ba,b 一定时,cc 是唯一的,确定的。因此在统计答案是不需要枚举 cc。 为了防止数对重复,我们规定:a>b>ca>b>c
再由题面知,1c1\le c,即 cc 不能为 00,也就是 aa 不能是 bb 的倍数的情况都成立。所以我们只要知道 (a,b)(a,b)bab\le a)的所有可能对数 sumsum(a,b)(a,b)bab\mid abb 能整除 aabab\le a)的对数 ansans。最终答案就是 sumanssum-ans
解释一下上面为什么 aa 可以与 bb 相等:是因为当 a=ba=b 时,bab\mid a 成立所以它在 sumsumansans 里都统计了一次,在最终答案里抵消了相当于没统计,所以上面的 aa 可以与 bb 相等。
sumsum 的计算十分简单,因为在 a=ia=i 时有 ii 个数对,所以 sum=1+2+3++N1+N=(1+N)×N2sum=1+2+3+\cdots+N-1+N=\dfrac{(1+N)\times N}{2}。 时间复杂度 O(1)O(1)
但是 ansans 就比较难在 1s 计算了,它的计算需要使用“数论分块”算法。在此,我就不献丑介绍了。不会的同学可以学习 P3935 Calculating 及其题解,它告诉了我们,如何在 N\sqrt{N} 的时间里求出 11NN 内的约数个数和。
代码如下:
CPP
for(int l=1,r;l<=N;l=r+1){
    r=N/(N/l);
    ans+=(N/r)%mod*((r-l+1)%mod)%mod;
    ans%=mod;
}
最后只要注意取模并统计答案就行了。
时间复杂度:O(N)O(\sqrt{N})

赛时代码

代码很短,不含注释只有 300 多 Byte。
CPP
#include<bits/stdc++.h>
#define int long long//记得开long long
using namespace std;
const int mod=998244353;//记得取模

int N,ans;

signed main(){
	cin>>N;
	for(int l=1,r;l<=N;l=r+1){//统计约数对数
		r=N/(N/l);
		ans+=(N/r)%mod*((r-l+1)%mod)%mod;
		ans%=mod;
	}
	int sum;//统计所有可能对数
	if(N%2) sum=(N+1)/2%mod*(N%mod)%mod;
	else sum=N/2%mod*((N+1)%mod)%mod;
	cout<<(sum-ans+mod)%mod;//输出答案
	
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...