bzoj4173 数学
欧拉(varphi)函数,变形还是很巧妙的
求:
首先,对(sum)下面那一坨进行变形
很容易知道,(nmod k+mmod k=n-lfloordfrac{n}{k}
floorcdot k+m-lfloordfrac{m}{k}
floorcdot k<2k)
那么对不等式同时除以(k),就是(1le dfrac{n+m}{k}-lfloordfrac{n}{k}
floor-lfloordfrac{m}{k}
floor<2)
然后把那个(frac{n+m}{k})来个下取整,这个式子就变成了(1),也就是:
所以只看那个(sum)就是:
然后又由于(lfloordfrac{n+m}{k} floor-lfloordfrac{n}{k} floor-lfloordfrac{m}{k} floor=1)只有(0,1)两个值,是(1)符合要求是(0)不符合,所以可以把上式继续拆:
下面考虑如何求(sum_{i=1}^nvarphi(i)lfloordfrac{n}{i} floor)就行了
想要推这个,先证明一个结论:(n=sum_{dmid n}varphi(d))
列举出如下分数:
(dfrac{1}{n},dfrac{2}{n},cdots,dfrac{n}{n})
然后把他们化简
当且仅当(dmid n,gcd(a,d)=1),分数(frac{a}{d})出现在其中
那么,以(d)为分母的分数有(varphi(d))个,(d)可以取遍(n)的所有因数
又因为这些分数的个数是(n),所以(n=sum_{dmid n}varphi(d))
那么把(sum)里面那一些,理解为(lfloorfrac{n}{i}
floor)个(varphi(i))相加
而从(1)到(n)中,有(lfloorfrac{n}{i}
floor)个数是(i)的倍数,所以我们枚举这(n)个数:
然后用刚才说的结论,变形为:
所以答案就清晰了:
最后由于数很大一定要频繁取模
#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;
}