bzoj4173 数学

bzoj4173 数学
欧拉\(\varphi\)函数,变形还是很巧妙的

求:

\[\varphi(n)\cdot\varphi(m)\cdot\sum_{n\bmod k+m\bmod k\ge k}\varphi(k)\bmod 998244353,n,m\le 10^{15} \]


首先,对\(\sum\)下面那一坨进行变形
很容易知道,\(n\bmod k+m\bmod k=n-\lfloor\dfrac{n}{k}\rfloor\cdot k+m-\lfloor\dfrac{m}{k}\rfloor\cdot k<2k\)
那么对不等式同时除以\(k\),就是\(1\le \dfrac{n+m}{k}-\lfloor\dfrac{n}{k}\rfloor-\lfloor\dfrac{m}{k}\rfloor<2\)
然后把那个\(\frac{n+m}{k}\)来个下取整,这个式子就变成了\(1\),也就是:

\[\lfloor\frac{n+m}{k}\rfloor-\lfloor\frac{n}{k}\rfloor-\lfloor\frac{m}{k}\rfloor=1 \]

所以只看那个\(\sum\)就是:

\[\sum_{\lfloor\frac{n+m}{k}\rfloor-\lfloor\frac{n}{k}\rfloor-\lfloor\frac{m}{k}\rfloor=1}\varphi(k) \]

然后又由于\(\lfloor\dfrac{n+m}{k}\rfloor-\lfloor\dfrac{n}{k}\rfloor-\lfloor\dfrac{m}{k}\rfloor=1\)只有\(0,1\)两个值,是\(1\)符合要求是\(0\)不符合,所以可以把上式继续拆:

\[\sum_{k=1}^{n+m}\varphi(k)\cdot(\lfloor\frac{n+m}{k}\rfloor-\lfloor\frac{n}{k}\rfloor-\lfloor\frac{m}{k}\rfloor) \]

\[\sum_{k=1}^{n+m}\varphi(k)\lfloor\frac{n+m}{k}\rfloor-\sum_{k=1}^n\varphi(k)\lfloor\frac{n}{k}\rfloor-\sum_{k=1}^m\varphi(k)\lfloor\frac{m}{k}\rfloor \]


下面考虑如何求\(\sum_{i=1}^n\varphi(i)\lfloor\dfrac{n}{i}\rfloor\)就行了

想要推这个,先证明一个结论:\(n=\sum_{d\mid n}\varphi(d)\)
列举出如下分数:
\(\dfrac{1}{n},\dfrac{2}{n},\cdots,\dfrac{n}{n}\)
然后把他们化简
当且仅当\(d\mid n,\gcd(a,d)=1\),分数\(\frac{a}{d}\)出现在其中
那么,以\(d\)为分母的分数有\(\varphi(d)\)个,\(d\)可以取遍\(n\)的所有因数
又因为这些分数的个数是\(n\),所以\(n=\sum_{d\mid n}\varphi(d)\)

那么把\(\sum\)里面那一些,理解为\(\lfloor\frac{n}{i}\rfloor\)个\(\varphi(i)\)相加
而从\(1\)到\(n\)中,有\(\lfloor\frac{n}{i}\rfloor\)个数是\(i\)的倍数,所以我们枚举这\(n\)个数:

\[\sum_{i=1}^n\varphi(i)\lfloor\dfrac{n}{i}\rfloor=\sum_{j=1}^n\sum_{i\mid j}\varphi(i) \]

然后用刚才说的结论,变形为:

\[\sum_{j=1}^n j \]

所以答案就清晰了:

\[\varphi(n)\cdot\varphi(m)\cdot\sum_{n\bmod k+m\bmod k\ge k}\varphi(k)=\varphi(n)\cdot\varphi(m)\cdot(\sum_{i=1}^{n+m}i-\sum_{i=1}^n i-\sum_{i=1}^m i)=\varphi(n)\cdot\varphi(m)\cdot n\cdot m \]


最后由于数很大一定要频繁取模

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline LL read(){
	register LL x=0;register int y=1;
	register char c=std::getchar();
	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
	return y?x:-x;
}
#define mod 998244353
inline LL phi(LL x){
	reg LL ret=x;
	int sqrt=std::ceil(std::sqrt(x));
	for(reg int i=2;i<=sqrt;i++){
		if(!(x%i)) ret=ret/i*(i-1);
		while(!(x%i)) x/=i;
	}
	if(x>1) ret=ret/x*(x-1);
	return ret;
}
int main(){
	LL n=read(),m=read();
	std::printf("%lld",phi(n)%mod*(phi(m)%mod)%mod*(n%mod)%mod*(m%mod)%mod);
	return 0;
}
上一篇:[CF938C] Constructing Tests - 构造


下一篇:整除(数论)分块