Leo_h

2333

【BZOJ3994】【SDOI2015】约数个数和

Description
设d(x)为x的约数个数,给定N、M,求 题目
Input

输入文件包含多组测试数据。
第一行,一个整数T,表示测试数据的组数。
接下来的T行,每行两个整数N、M。

Output

T行,每行一个整数,表示你所求的答案。

Sample Input

2
7 4
5 6

Sample Output

110
121

HINT
1<=N, M<=50000
1<=T<=50000

%%%ZZJ
%%%zmoiynlp
从这俩人的题解中分别吸取一些很神的地方自己写一份题解

首先考虑i* j的一个因数是由i的一个因数p和j的一个因数q相乘而得的,但是这里会有重复的情况,比如i=4,j=6的时候,因数4就由4*1 和 2*2累加两次。
解决方案是,让一个i和j的公共质因子优先乘到p上,等到i除去p已经没有这个质因子,在乘到q上,这样合法的方案一定有(ip,j)==1
所以ni=1mj=1d(ij)

=ni=1mj=1p|iq|j[(ip,q)==1]

=ni=1mj=1p|iq|j[(p,q)==1]

=np=1[np]mq=1[mq][(p,q)==1]

=np=1[np]mq=1[mq]d|p,d|qμ(d)

=min(n,m)d=1μ(d)n/dp/d=1[np]m/dq/d=1[mq]

=min(n,m)d=1μ(d)ndp=1[[nd]p]mdq=1[[md]q]

由经验,我们可以发现 ni=1[ni]是d函数的前缀和
证明:对于每一个i,n/i是1~n中整除i的数的个数
于是可以 线性筛法求出μ和d的前缀和,对d分块就解决了

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define maxn 50005
#define to i*prime[j]
#define long long long
int t,n,m;
int prime[maxn];
int p;
int miu[maxn];//used_as_prefix_sum_later
int d[maxn];
int tmp[maxn];
void sieve()
{
    miu[1]=1;
    d[1]=1;
    for(int i=2;i<maxn;i++)
    {
        if(!tmp[i])
        {
            miu[i]=-1;
            prime[++p]=i;
            d[i]=2;
            tmp[i]=2;
        }
        for(int j=1;j<=p&&to<maxn;j++)
        {
            if(i%prime[j]==0) 
            {
                tmp[to]=tmp[i]+1;
                d[to]=d[i]/tmp[i]*tmp[to];
                miu[to]=0;
                break;
            }
            else
            {
                tmp[to]=2;
                d[to]=d[i]*tmp[to];
                miu[to]=-miu[i];
            }
        }
        miu[i]+=miu[i-1];
        d[i]+=d[i-1];
    }
}
int main()
{
    //freopen(".in","r",stdin);
    sieve();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        long ans=0;
        for(int i=1,p;i<=n&&i<=m;i=p+1)
        {
            p=min(m/(m/i),n/(n/i));
            ans+=(long)(miu[p]-miu[i-1])*d[m/i]*d[n/i];
        } 
        printf("%lld\n",ans);
    }
}
阅读更多
版权声明:本文为博主原创文章,转载请注明源网址blog.csdn.net/leo_h1104 https://blog.csdn.net/Leo_h1104/article/details/52663906
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

【BZOJ3994】【SDOI2015】约数个数和

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭