[NOI2010]能量采集
作者:互联网
Description:
求$ \sum_{i=1}^n \sum_{j=1}^m gcd(i,j)*2-1$
Hint:
\(n,m<=10^5\)
Solution:
$ Ans=2*\sum_{i=1}^n \sum_{j=1}^m gcd(i,j) -n*m $
$\sum_{i=1}^n \sum_{j=1}^m gcd(i,j)=\sum_{T=1}^n\sum_{d=1}^{T } \mu(\frac{T}{d}) *d *\lfloor \frac{n}{T} \rfloor \lfloor \frac{m}{T} \rfloor $
$ =\sum_{T=1}^n \phi (T) *\lfloor \frac{n}{T} \rfloor \lfloor \frac{m}{T} \rfloor $
线性筛即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mxn=1e5+5;
int tot,phi[mxn],p[mxn],vis[mxn];
ll sum[mxn];
void sieve(int n)
{
phi[1]=1;
for(int i=2;i<=n;++i) {
if(!vis[i]) phi[i]=i-1,p[++tot]=i;
for(int j=1;j<=tot&&p[j]*i<=n;++j) {
vis[p[j]*i]=1;
if(i%p[j]) phi[p[j]*i]=phi[i]*(p[j]-1);
else {
phi[p[j]*i]=phi[i]*p[j];
break ;
}
}
}
for(int i=1;i<=n;++i) sum[i]=sum[i-1]+phi[i];
}
int main()
{
int n,m; scanf("%d%d",&n,&m);
if(n>m) swap(n,m); ll ans=0; sieve(100000);
for(int l=1,r;l<=n;l=r+1) {
r=min(n/(n/l),m/(m/l));
ans+=(sum[r]-sum[l-1])*(n/l)*(m/l);
}
printf("%lld",ans-1ll*n*m+ans); //n*m可能会炸,开long long
}
标签:lfloor,frac,int,sum,rfloor,mxn,采集,NOI2010,能量 来源: https://www.cnblogs.com/list1/p/10391082.html