听小乐乐的去做NOI了~\(≧▽≦)/~啦啦啦
一开始sha bi了,没考虑2,3->4,6。。。样例骗人QAQ
容易得到答案就是∑i(1<=i<=n)∑j(1<=j<=m)gcd(i,j)*2-1
但暴力是nm的,GG
我们转换一下思路,设f[i]为gcd为i的点对个数,怎么求f[i]呢?直接算好像并不行,考虑容斥,显然(n/i)*(m/i)就是有公因数为i的点对个数,然后减去f[2*i],f[3*i]...就好了
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<iostream> #include<string> #include<ctime> #include<queue> #include<map> #include<set> #include<vector> typedef long long LL; using namespace std; const int N=100010; LL n,m,k,ans,f[N]; LL read() {LL d=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=(d<<3)+(d<<1)+c-48,c=getchar(); return d*f;} void judge(){freopen(".in","r",stdin); freopen(".out","w",stdout);} int main() { //judge(); n=read(); m=read(); int ljj=max(n,m),pjy=min(n,m); for (int i=ljj;i>=1;i--) { f[i]=(n/i)*(m/i); for (int j=2*i;j<=pjy;j+=i) f[i]-=f[j]; } for (LL i=1;i<=ljj;i++) ans+=f[i]*(2*i-1); printf("%lld",ans); return 0; }