【BZOJ-4173】数学 欧拉函数 + 关于余数的变换
4173: 数学
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 306 Solved: 163
[Submit][Status][Discuss]
Description
Input
输入文件的第一行输入两个正整数 。
Output
如题
Sample Input
Sample Output
HINT
N,M<=10^15
Source
Solution
数论好题,开始无从下手,推导后感觉新姿势++
题目大意:求$\varphi(n)*\varphi(m)*\sum_{k\in S(n,m)}\varphi(k) mod p$其中$p=998244353$且$S(n,m)=\left \{n mod k+m mod k>=k\right \}$
首先把式子拆解一下,先看$S(n,m)=\left \{n mod k+m mod k>=k\right \}$:
不妨设$n=q_{1}*k+r_{1}$,$m=q_{2}*k+r_{2}$
那么很显然有:$n mod k=r_{1}$,$n / k=q_{1}$,$m mod k=r_{2}$,$m / k=q_{2}$
那么$S(n,m)=\left \{n mod k+m mod k>=k\right \}$就可以先化成$S(n,m)=\left \{r_{1}+r_{2}>=k\right \}$
那么根据上述,同样的有:$n+m=(q_{1}+q_{2})*k+(r_{1}+r_{2})$
很显然$(r_{1}+r_{2})/k<=1$,如果有$r_{1}+r_{2}>=k$,那么$(n+m) mod k=r_{1}+r_{2}-k$,且$(n+m)/k=q_{1}+q_{2}+1$
这样发现,开始的$S(n,m)=\left \{n mod k+m mod k>=k\right \}$就可以等价为$\frac{n+m}{k}-\frac{n}{k}-\frac{m}{k}=1$
所以$\sum_{k\in S(n,m)}\varphi(k)$就可以等价成$\frac{n+m}{k}\sum_{k=1}^{n+m}\varphi(k)-\frac{n}{k}\sum_{k=1}^{n}\varphi(k)-\frac{m}{k}\sum_{k=1}^{m}\varphi(k)$
根据有一个性质$n=\sum_{d|n}\varphi(d)$那么上述式子可以转化成:$\sum_{i=1}^{n+m}-\sum_{i=1}^{n}-\sum_{i=1}^{m}$
根据求和公式$\frac{n(n-1)}{2}$再变换为$\frac{(n+m)(n+m-1)}{2}-\frac{n(n-1)}{2}-\frac{m(m-1)}{2}$
化简一下发现$\frac{(n+m)(n+m-1)}{2}-\frac{n(n-1)}{2}-\frac{m(m-1)}{2}=n*m$
所以最后的答案为$ans=\varphi(n)*\varphi(m)*n*m$
那么用$\sqrt{n}$的时间复杂度求出$\varphi$即可
Code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; long long read() { long long x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define p 998244353 long long n,m; long long phi(long long x) { long long y=(long long)sqrt(n+0.5); long long re=x; for(long long i=2; i<=y; i++) if(!(x%i)) { re=re/i*(i-1); while(!(x%i)) x/=i; } if(x>1) re=re/x*(x-1); return re; } int main() { n=read(),m=read(); long long ans; ans=((((phi(n)%p)*(phi(m)%p))%p*(m%p))%p*(n%p))%p; printf("%lld\n",ans); return 0; }
很早以前写的..博客搬家没搬进来...