BZOJ 2005 容斥原理

思路:

题目让求的是 Σgcd(i,j) (i<=n,j<=m) n,m不同 没法线性筛
怎么办?
容斥原理!!
f[x]表示gcd(i,j)=x的个数

g[x]为 存在公约数=x 的数对(i,j)的个数
g(x)=(n/x)*(m/x)

那么f[x]就是 g(x)-f(2*x)-f(3*x)-…… -f(i*x) (i*x<=min(n,m))

从后往前算 (这个显然吧 要不怎么减)

Σf(x)*2 -n*m就是答案啦~~

复杂度的话嘛
O(n)+O(n/2)+O(n/3)…..+O(n/i)=O(nlogn)

//By SiriusRen
#include <cstdio>
using namespace std;
#define int long long
int f[100050],ans;
signed main(){
    int n,m,mx;
    scanf("%lld%lld",&n,&m),mx=n<m?n:m;
    for(int i=mx;i;i--){
        f[i]=(n/i)*(m/i);
        for(int j=2;i*j<=mx;j++)
            f[i]-=f[i*j];
        ans+=f[i]*2*i;
    }
    printf("%lld\n",ans-(long long)n*m);
}

这里写图片描述

posted @ 2017-01-10 15:56  SiriusRen  阅读(...)  评论(...编辑  收藏