[BZOJ 2301] Problem B

Link:

https://www.lydsy.com/JudgeOnline/problem.php?id=2301

 

Algorithm: 

令$g(n,m)$表示在$1<=x<=n,1<=y<=m$满足$gcd(x,y)$是$k$的$(x,y)$的对数。

那么由容斥原理可得$ans=g(b,d)+g(a−1,c-1)−g(a-1,d)-g(b,c−1,k)$

 

满足$gcd(x,y)$是$k$的$(x,y)$的对数也等价于$(x,y)$互质的对数($1\le x\le n/k,1\le y\le m/k$),即

 $g(n,m,k)=g(n/k,m/k,1)$

 

令$f(i)$表示满足$gcd(x,y)=i$时$(x,y)$的对数

 $F(i)$表示满足$i|gcd(x,y)的(x,y)$的对数,则$F(i)=\lfloor n_i \rfloor \lfloor m_i \rfloor$。

 

于是我们发现这是一个具有倍数关系的莫比乌斯反演:

$F(i)=\sum_{i | d} f(d)$    <->     $f(i)=\sum_{i|d} miu(d/i)*(n/d)*(m/d)$

 

接下来就要优化每次求f(i)的复杂度,需要将其降至$O(logN)$,

发现$[n/d]$最多有$2sqrt(n)$个取值,那么 $(n/d)*(m/d)$就至多有$2sqrt(n)+2sqrt(m)$个取值

 (并不是$*$,对于每个$d \in n/(sqrt(n)+1)<d\le n $, $(n/d)*(m/d)$仍只有一个值)

 

于是我们发现会有连续的一段$(n/d)*(m/d)$的值相同,便可以使用分块来优化

注意其中转移到下一块的处理技巧:$i=x/(x/i)+1$

个人认为$x/(x/i)$表示根据当前$x/i$的值找出最大的$i′$,再加一就是另一个$x/i$值了

 

Code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN=5e4+10;
inline ll read()
{
    char ch;ll num,f=0;
    while(!isdigit(ch=getchar())) f|=(ch=='-');
    num=ch-'0';
    while(isdigit(ch=getchar())) num=num*10+ch-'0';
    return f?-num:num;
}

int a,b,c,d,k;
int sum[MAXN],mo[MAXN],pri[MAXN],cnt;
bool mark[MAXN];
void getmo()
{
    mo[1]=1;
    for(int i=2;i<=5e4;i++)
    {
        if(!mark[i]){mo[i]=-1;pri[++cnt]=i;}
        for(int j=1;j<=cnt && i*pri[j]<=5e4;j++)
        {
            mark[i*pri[j]]=1;
            if(i%pri[j]==0){mo[i*pri[j]]=0;break;}
            else mo[i*pri[j]]=-mo[i];
        }
    }
    for(int i=1;i<=5e4;i++)
        sum[i]=sum[i-1]+mo[i];
}
int cal(int n,int m)
{
    n/=k;m/=k;
    if(n>m)swap(n,m);
    int ret=0,pos;
    for(int i=1;i<=n;i=pos+1)
    {
        pos=min(n/(n/i),m/(m/i));
        ret+=(sum[pos]-sum[i-1])*(n/i)*(m/i);
    }
    return ret;
}
int main()
{
    getmo();
    int T=read();
    while(T--)
    {
        a=read();b=read();c=read();d=read();k=read();
        int res=cal(a-1,c-1)+cal(b,d)-cal(a-1,d)-cal(b,c-1);
        printf("%d\n",res);
    }
    return 0;
}

 

 Review:

1、 将gcd(x,y)=k这样的条件转化为x/k与y/k互质

      方便使用欧拉函数或莫比乌斯反演解题

 

2、使用分块对莫比乌斯反演的优化

posted @ 2018-05-23 16:24  NewErA  阅读(136)  评论(0编辑  收藏  举报