Victoryztk有一个长方形的矿场,矿物排列得非常整齐,一共有n列,每列有m块,矿石的横竖间距都一样,因此对于每一棵矿石,Victoryztk可以用一个坐标(x, y)来表示,其中x的范围是1至n,表示是在第x列,y的范围是1至m,表示是在第x列的第y块。
由于检查矿物的机器较大,不便移动,Victoryztk将它放在了一个角上,坐标正好是(0, 0)。矿物检查机器在检查的过程中有一定的能量损失。如果一块矿石与矿物检查机器连接而成的线段上有k块矿石,则机器磨损为2k + 1。
例如,当矿物检查机器检查坐标为(2, 4)的矿物时,由于连接线段上存在一块矿石(1, 2),会产生3的机器磨损。注意,如果一块矿石与矿物检查机器连接的线段上没有矿石,则机器磨损为1。现在要计算总的机器磨损。
下面给出了一个机器磨损的例子,其中n = 5,m = 4,一共有20块矿石,在每块矿石上标明了矿物检查机器检查它时产生的机器磨损。 在这个例子中,总共产生了36的能量损失。

Input

仅包含一行,为两个整数n和m。

Output

仅包含一个整数,表示总共产生的能量损失。

Sample Input

【样例输入1】
5 4
【样例输入2】
3 4

Sample Output

【样例输出1】
36
【样例输出2】
20
对于100%的数据:1 ≤ n, m ≤ 100,000。

Hint

15*1+3*3+5*1+7*1=36

红书上的Mobius函数居然是o(nlogn)的。。。跑了4秒多,弄了个线性筛600ms

https://blog.csdn.net/coldfresh/article/details/77099943

这个把它弄到o(n)了  60ms

 

#include<bits/stdc++.h>
using namespace std;
const int n=1<<20;
int mu[n];
void getMu()
{
    memset(mu,0,sizeof(mu));
    for(int i=1; i<=n; i++)
    {
        int target=i==1?1:0;
        int delta=target-mu[i];
        mu[i]=delta;
        for(int j=i+i; j<=n; j+=i)
            mu[j]+=delta;
    }
}
const int MAXN=1e6+5;
typedef long long LL;
bool check[MAXN+10];
long long prime[MAXN+10];

void Moblus()
{
    memset(check,false,sizeof(check));
    mu[1] = 1;
    long long tot = 0;
    for(long long i = 2; i <= MAXN; i++)
    {
        if( !check[i] )
        {
            prime[tot++] = i;
            mu[i] = -1;
        }
        for(long long j = 0; j < tot; j++)
        {
            if(i * prime[j] > MAXN) break;
            check[i * prime[j]] = true;
            if( i % prime[j] == 0)
            {
                mu[i * prime[j]] = 0;
                break;
            }
            else
            {
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
}

long long f[n];
int main()
{

    int a,b;
    Moblus();
    while(scanf("%d%d",&a,&b)!=EOF)
    {
        long long ans=0;

        int c=min(a,b);
        for(int i=1; i<=n; i++)
            f[i]=1ll*(a/i)*(b/i);

        for(int i=1; i<=c; i++)
        {
            long long temp=0;
            for(int j=1; j<=c; j++)
            {
                long long h=i*j;
                if(i*j<=c)
                {
                    temp+=(long long)mu[j]*f[h];
                }
                else break;
            }
            ans+=temp*i;
        }
        cout<<2*ans-(long long)a*b<<endl;
    }
}