标签:col 为我 main gcd swap nbsp 抽象 void 个数
感觉莫反学的很不扎实。。很虚。。bs lmy
为什么这么说,是因为我连求F(i)要把他转换成F(1)再求都不知道。。。。
那么这题抽象点看ans就是等于这个
ans = n*m + sigema(1~n)x sigema(1~m)y (gcd(x,y)-1)*2
F(i)表示 gcd(x,y)==i 的个数,那么ans = n*m + sigema(1~n)i (n-1)*2*F(i)
G(i)表示 gcd(x,y)==i的倍数 的个数
那么G(i)=(n/i)*(m/i)
然后反演形式2 F(i)=sigma(u(d/i)*G(d)) (其中n|d)
PS(无脑long long)
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; LL pr,prime[110000],u[110000]; bool v[110000]; void mobius_inversion() { pr=0;u[1]=1; memset(v,true,sizeof(v)); for(int i=2;i<=100000;i++) { if(v[i]==true) { prime[++pr]=i; u[i]=-1; } for(int j=1;j<=pr&&i*prime[j]<=100000;j++) { v[i*prime[j]]=false; if(i%prime[j]==0){u[i*prime[j]]=0;break;} u[i*prime[j]]=-u[i]; } u[i]+=u[i-1]; } } LL getFi(LL n,LL m) { LL t=min(n,m),last;LL Fi=0; for(LL d=1;d<=t;d=last+1) { last=min(n/(n/d),m/(m/d)); LL Gd=(n/d)*(m/d); Fi+=(u[last]-u[d-1])*Gd; } return Fi; } int main() { mobius_inversion(); LL n,m; scanf("%lld%lld",&n,&m); if(n>m)swap(n,m); LL ans=n*m; for(int i=1;i<=n;i++) { ans+=(i-1)*2*getFi(n/i,m/i); } printf("%lld\n",ans); return 0; }
标签:col 为我 main gcd swap nbsp 抽象 void 个数
原文地址:http://www.cnblogs.com/AKCqhzdy/p/7903819.html