【BZOJ4173】数学
4173: 数学
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 528 Solved: 258
[Submit][Status][Discuss]
Description
Input
输入文件的第一行输入两个正整数 。
Output
如题
Sample Input
5 6
Sample Output
240
HINT
N,M<=10^15
sol:推公式
$m mod k + n mod k \ge k$
$= n- k* \lfloor \frac{n}{k} \rfloor + m - k* \lfloor \frac{m}{k} \rfloor \ge k$
$=\lfloor \frac{(n+m)}{k} \rfloor - \lfloor \frac{n}{k} \rfloor - \lfloor \frac{m}{k} \rfloor = 1$
然后上述式子合并一下 然后类似反演的推一下就好了 我真是懒得写了QAQ
中途需要硬拆数列前缀和
UPD:
哇我这篇排名居然这么高 我就再写一点吧
考虑容斥 那么$\sum_{\lfloor \frac{(n+m)}{k} \rfloor - \lfloor \frac{n}{k} \rfloor - \lfloor \frac{m}{k} \rfloor = 1} \phi(k)$
$=\sum_{k=1}^{n+m}\phi(k)*\lfloor \frac{(n+m)}{k} \rfloor - \sum_{k=1}^{n}\phi(k) * \lfloor \frac{n}{k} \rfloor - \sum_{k=1}^{m}\phi(k)*\lfloor \frac{m}{k} \rfloor$
根据数论知识 我们有$n=\sum_{d|n}\phi(d)$
于是简化式子 $\sum_{i=1}^{n+m}i-\sum_{i=1}^{n}i-\sum_{i=1}^{m}i$
等差数列求和 得到该式为$n*m$(不信自己证明)
至于为啥$n- k* \lfloor \frac{n}{k} \rfloor + m - k* \lfloor \frac{m}{k} \rfloor \ge k=\lfloor \frac{(n+m)}{k} \rfloor - \lfloor \frac{n}{k} \rfloor - \lfloor \frac{m}{k} \rfloor = 1$ 消k我还真没搞懂 看到某个大爷说显然只有两种取值 不是很懂……?
然后答案就是$\phi(n)*\phi(m)*n*m$复杂度$O(\sqrt{n}*logn)$
/*To The End Of The Galaxy*/ #include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<iomanip> #include<stack> #include<map> #include<set> #include<cmath> #include<complex> #define debug(x) cerr<<#x<<"="<<x<<endl #define INF 0x7f7f7f7f #define llINF 0x7fffffffffffll using namespace std; typedef pair<int,int> pii; typedef long long ll; inline int init() { int now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(c=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } inline long long llinit() { long long now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(c=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } ll ans,mod; ll getphi(ll x) { ll ret=x,tmp=x; for(ll i=2;(ll)i*i<=tmp;i++) { if(x%i==0) { ret/=i;ret*=(i-1); while(x%i==0) { x/=i; } } if(x==1)break; } if(x>1)ret/=x,ret*=(x-1); return ret%mod; } #ifdef unix #define LLD "%lld" #else #define LLD "%I64d" #endif int main() { ll n,m;mod=998244353LL; n=llinit();m=llinit(); ans=(((((n%mod)*(m%mod))%mod)*getphi(n)%mod)*getphi(m)%mod)%mod; printf(LLD,ans); return 0; }