【BZOJ4173】数学 题解(数论)
前言:体验到了推式子的快感orz
题目大意:求$\varphi(n)*\varphi(m)*\sum_{n\ mod\ k+m\ mod\ k\geq k} \varphi(k)\ mod\ 998244353$
---------------------------
设$n=q_1k+r_1,m=q_2k+r_2$,那么$q_1=\lfloor \frac{n}{k} \rfloor,q_2=\lfloor \frac{m}{k} \rfloor$。
$n+m=(q_1+q_2)k+r_1+r_2$
$(n+m)-(q_1+q_2)k=r_1+r_2$
$\lfloor \frac{n+m}{k} \rfloor-\lfloor \frac{n}{k} \rfloor-\lfloor \frac{m}{k} \rfloor=r_1+r_2=1$
所以现在变为:找到满足上式的$k$。
我们先给出一个式子:
$ans=\sum\limits_{i=1}^{n+m}\varphi(k)*\lfloor \frac{n+m}{k} \rfloor-\sum\limits_{i=1}^n \varphi(k)*\lfloor \frac{n}{k} \rfloor-\sum\limits_{i=1}^m \varphi(k)*\lfloor \frac{m}{k} \rfloor$
这个式子是什么意思?
对于$(\lfloor \frac{n+m}{k} \rfloor-\lfloor \frac{n}{k} \rfloor-\lfloor \frac{m}{k} \rfloor)*\varphi(k)$:
如果$k$满足条件,那么系数为$1$,对答案有贡献。如果$k$不合法那么系数为$0$,对答案是没有贡献的。所以上面给出的式子可以计算所有合法的答案。
现在我们尝试对$\sum\limits_{i=1}^n \varphi(k)*\lfloor \frac{n}{k} \rfloor$进行化简。
有这样一个关系:$\sum\limits_{i=1}^n i=\sum\limits_{i=1}^n \sum\limits_{k|i}\varphi(k)=\sum\limits_{i=1}^n \varphi(k)*\lfloor \frac{n}{k} \rfloor$
证明:$\sum\limits_{i=1}^n i=\sum\limits_{i=1}^n \sum\limits_{k|i}\varphi(k)$
对于一个数$i$,在小于等于它的数中有这样的关系:
1.最大公约数为$1$,记为$G_1$,个数显然是$\varphi(i)$
2.最大公约数为$2$,记为$G_2$,个数是$\varphi(i/2)$
$\cdots$
i.最大公约数为$i$,记为$G_i$,个数为$1$。
这些集合的并集大小为$i$,所以上述等式成立。
现在来看$\sum\limits_{i=1}^n \sum\limits_{k|i}\varphi(k)=\sum\limits_{i=1}^n \varphi(k)*\lfloor \frac{n}{k} \rfloor$
对于左式,其意义为考虑每个$i$对答案的贡献;而对于右式,其意义为考虑每个合法的$k$对答案的贡献。二者对于答案的总贡献是相同的,所以等式成立。
经过化简,最终答案为$\varphi(n)*\varphi(m)*n*m$
代码:
#include<bits/stdc++.h> #define int long long using namespace std; const int mod=998244353; int n,m,ans; inline int phi(int x) { int res=x,m=x; for (int i=2;i*i<=m;i++) { if (x%i) continue; res=res/i*(i-1); while(!(x%i)) x/=i; } if (x>1) res=res/x*(x-1); return res%mod; } signed main() { cin>>n>>m; ans=((n%mod)*(m%mod))%mod; ans*=phi(n),ans%=mod; ans*=phi(m),ans%=mod; printf("%lld",(ans+mod)%mod); return 0; }