傳送門php
能夠直接經過一些推算髮現題目實際上就是在求:c++
\[ Ans=2\times \sum_{i=1}^{n}\sum_{j=1}^{m}(gcd(i,j)-1 ) \]spa
把裏面的\(1\)提出來,式子變成:code
\[ Ans=2\times\sum_{i=1}^{n}\sum_{j=1}^{m}gcd(i,j)-2\times nm \]ci
能夠發現前面那個式子好像很熟悉,咱們設:get
\[ S(n)=\sum_{i=1}^{n}\sum_{j=1}^{m}gcd(i,j) \]it
那麼咱們把這個式子化出來就能夠了。
\[ \begin{aligned} S(n)&=\sum_{i=1}^{n}\sum_{j=1}^{m}gcd(i,j)\\ &=\sum_{d=1}^{min(n,m)}\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=d]d\\ &=\sum_{d=1}^{min(n,m)}d\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=d]\\ &=\sum_{d=1}^{min(n,m)}d\sum_{d\mid x}\mu(\frac{x}{d})\lfloor\frac{n}{x}\rfloor\lfloor\frac{m}{x}\rfloor\\ &=\sum_{d=1}^{min(n,m)}d\sum_{T=1}^{min(\frac{n}{d},\frac{m}{d})}\mu(T)\lfloor\frac{n}{dT}\rfloor\lfloor\frac{m}{dT}\rfloor\\ &=\sum_{d=1}^{min(n,m)}\sum_{d\mid T}^{min(n,m)}d\mu(\frac{T}{d})\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\\ &=\sum_{T=1}^{min(n,m)}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{d\mid T}^{min(n,m)}\mu(\frac{T}{d})\\ &=\sum_{T=1}^{min(n,m)}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\varphi(T) \end{aligned} \]
化到這個地方就差很少了,這個式子明顯是能夠整除分塊作的。可是,這個題數據支持線性作法。。。
直接作就行。class
#include <bits/stdc++.h> using namespace std; const int MAXN=1e6+7; #define ll long long int prime[MAXN],n,m; ll phi[MAXN],sum; bool vis[MAXN]; inline void get_phi(int N) { phi[1]=1; for(int i=2;i<=N;i++){ if(!vis[i]){ prime[++prime[0]]=i; phi[i]=i-1; } for(int j=1;j<=prime[0];j++){ if(i*prime[j]>N) break; vis[i*prime[j]]=1; if(i%prime[j]==0){ phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*(prime[j]-1); } } } int main() { cin>>n>>m; sum=-1ll*n*m; get_phi(1000000); for(int i=1;i<=min(n,m);i++) sum+=1ll*2*(n/i)*(m/i)*phi[i]; printf("%lld\n", sum); }