BZOJ 3994 Sdoi2015 约数个数和 莫比乌斯反演

题目大意:求∑ni=1∑mj=1d(ij)

首先我们有一个很神的结论:

∑ni=1∑mj=1d(ij)=∑ni=1∑mj=1?ni??mj?[gcd(i,j)==1]

这个结论是怎么来的呢?我们可以先证明这个:

d(nm)=∑i|n∑j|m1?1[gcd(i,j)==1]

显然这个式子的前缀和就是上面的式子

现在我们来证明这个式子是对的

我们分开讨论每一个质数p对答案的贡献

不妨设n=n′?pk1,m=m′?pk2

那么左式中p的贡献显然是k1+k2+1

右式中只考虑p的话,满足要求的数对(i,j)只有(pk1,1),(pk1?1,1),...,(p,1),(1,1),(1,p),...,(1,pk2?1),(1,pk2),共有k1+k2+1对

因此等式成立,原式得证。

然后怎么搞还用我说么= =?

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 50500
using namespace std;

int n,m;

int mu[M],d[M],cnt[M],prime[M],tot;
bool not_prime[M];
void Linear_Shaker()
{
    int i,j;
    mu[1]=1;d[1]=1;
    for(i=2;i<=50000;i++)
    {
        if(!not_prime[i])
        {
            prime[++tot]=i;
            mu[i]=-1;
            d[i]=2;
            cnt[i]=1;
        }
        for(j=1;prime[j]*i<=50000;j++)
        {
            not_prime[prime[j]*i]=true;
            if(i%prime[j]==0)
            {
                mu[prime[j]*i]=0;
                d[prime[j]*i]=d[i]/(cnt[i]+1)*(cnt[i]+2);
                cnt[prime[j]*i]=cnt[i]+1;
                break;
            }
            mu[prime[j]*i]=-mu[i];
            d[prime[j]*i]=d[i]<<1;
            cnt[prime[j]*i]=1;
        }
    }
    for(i=1;i<=50000;i++)
    {
        mu[i]+=mu[i-1];
        d[i]+=d[i-1];
    }
}
long long Solve()
{
    long long re=0;
    int i,last;
    if(n>m) swap(n,m);
    for(i=1;i<=n;i=last+1)
    {
        last=min(n/(n/i),m/(m/i));
        re+=(long long)(mu[last]-mu[i-1])*d[n/i]*d[m/i];
    }
    return re;
}
int main()
{
    int T;
    Linear_Shaker();
    for(cin>>T;T;T--)
    {
        scanf("%d%d",&n,&m);
        printf("%lld\n",Solve());
    }
    return 0;
}
时间: 2024-10-01 19:08:01

BZOJ 3994 Sdoi2015 约数个数和 莫比乌斯反演的相关文章

BZOJ 3994 [SDOI2015]约数个数和 (神定理+莫比乌斯反演)

3994: [SDOI2015]约数个数和 Time Limit: 20 Sec  Memory Limit:128 MB Submit: 239  Solved: 176 [Submit][Status][Discuss] Description 设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Output T行,每行一个整数,表示你所求的答案. Sample Input 2 7

BZOJ 3994: [SDOI2015]约数个数和

3994: [SDOI2015]约数个数和 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 898  Solved: 619[Submit][Status][Discuss] Description 设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Output T行,每行一个整数,表示你所求的答案. Sample Input 2 7

[SDOI2015] 约数个数和 (莫比乌斯反演)

[SDOI2015]约数个数和 题目描述 设d(x)为x的约数个数,给定N.M,求 \(\sum^N_{i=1}\sum^M_{j=1}d(ij)\) 输入输出格式 输入格式: 输入文件包含多组测试数据.第一行,一个整数T,表示测试数据的组数.接下来的T行,每行两个整数N.M. 输出格式: T行,每行一个整数,表示你所求的答案. 输入输出样例 输入样例#1: 2 7 4 5 6 输出样例#1: 110 121 说明 \(1<=N, M<=50000\) \(1<=T<=50000\

【bzoj3994】[SDOI2015]约数个数和 莫比乌斯反演

题目描述 设d(x)为x的约数个数,给定N.M,求   输入 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. 输出 T行,每行一个整数,表示你所求的答案. 样例输入 2 7 4 5 6 样例输出 110 121 题解 莫比乌斯反演 根据 bzoj4176 推出的结论, 那么就有: 预处理mu及其前缀和. 由于要处理多组询问,所以需要用O(n√n)的时间预处理出f,然后对于每组询问分块来求. #include <cstdio> #incl

【刷题】BZOJ 3994 [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 Solution 莫比乌斯反演 但这题更多的是套路 首先,一个神奇的东东:\(d(nm)= \

luogu P3327 [SDOI2015]约数个数和 莫比乌斯反演

题面 我的做法基于以下两个公式: \[[n=1]=\sum_{d|n}\mu(d)\] \[\sigma_0(i*j)=\sum_{x|i}\sum_{y|j}[gcd(x,y)=1]\] 其中\(\sigma_0(n)\)表示\(n\)的约数个数 第一个公式是莫比乌斯函数的基本性质,至于第二个公式的证明,可以考虑\(i*j\)中每一个质因子对 \(\sigma_0(i*j)\) 的贡献,对于一个质因子 \(p\) ,若它在 \(i\) 中的次数为 \(k_1\) ,它在 \(j\) 中的次数为

【BZOJ 3994】3994: [SDOI2015]约数个数和(莫比乌斯反演)

3994: [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 Source Round 1 感谢yts199

3994: [SDOI2015]约数个数和

3994: [SDOI2015]约数个数和 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 858  Solved: 587[Submit][Status][Discuss] Description 设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接下来的T行,每行两个整数N.M. Output T行,每行一个整数,表示你所求的答案. Sample Input 2 7

[BZOI 3994] [SDOI2015]约数个数和

[BZOI 3994] [SDOI2015]约数个数和 题面 设d(x)为x的约数个数,给定N.M,求\(\sum _{i=1}^n \sum_{i=1}^m d(i \times j)\) T组询问,\(N,M,T \leq 50000\) 分析 首先有一个结论 \[d(nm)= \sum _{i |n} \sum _{j|m} [gcd(i,j)=1]\] 这是因为nm的约数都可以表示为\(i \times \frac{m}{j}\)的形式,并且为了不重复算,要保证\(gcd(i,j)=1\