洛谷P3327 [SDOI2015]约数个数和

如果不知道莫比乌斯 这里有我的超精简版入门Mobius
记录我初学莫比乌斯做了整整一天还迷迷糊糊

题目简述:
∑ i = 1 n ∑ ​ j = 1 m ​ d ( i j ) d ( i j ) 为 i ∗ j 的 约 数 ∑_{i=1}^n∑_{​j=1}^m​d(ij)\\d(ij)为i*j的约数 i=1nj=1md(ij)d(ij)ij(多组数据)

必要性质:
​ d ( i j ) = ∑ x ∣ i ∑ y ∣ j g c d ( x , y ) = 1 ​d(ij)=∑_{x|i}∑_{y|j}gcd(x,y)=1 d(ij)=xiyjgcd(x,y)=1
证明:
不会

解题思路:
​ 所 求 即 ∑ i = 1 n ∑ ​ j = 1 m ∑ x ∣ i ∑ y ∣ j g c d ( x , y ) = 1 ​所求即∑_{i=1}^n∑_{​j=1}^m∑_{x|i}∑_{y|j}gcd(x,y)=1 i=1nj=1mxiyjgcd(x,y)=1 根 据 莫 比 乌 斯 函 数 的 性 质 可 转 换 为 ∑ i = 1 n ∑ ​ j = 1 m ∑ x ∣ i ∑ y ∣ j ∑ d ∣ g c d ( x , y ) μ ( d ) 根据莫比乌斯函数的性质可转换为\\ ∑_{i=1}^n∑_{​j=1}^m∑_{x|i}∑_{y|j}∑_{d|gcd(x,y)}μ(d)\\ i=1nj=1mxiyjdgcd(x,y)μ(d) 转 换 为 转换为\\ ∑ i = 1 n ∑ ​ j = 1 m ∑ x ∣ i ∑ y ∣ j ∑ d = 1 m i n ( n , m ) μ ( d ) ∗ [ d ∣ g c d ( x , y ) ] ∑_{i=1}^n∑_{​j=1}^m∑_{x|i}∑_{y|j}∑_{d=1}^{min(n,m)}μ(d)*[d|gcd(x,y)] i=1nj=1mxiyjd=1min(n,m)μ(d)[dgcd(x,y)] 即 ∑ d = 1 m i n ( n , m ) μ ( d ) ∑ i = 1 n ∑ ​ j = 1 m ∑ x ∣ i ∑ y ∣ j [ d ∣ g c d ( x , y ) ] 即\\ ∑_{d=1}^{min(n,m)}μ(d)∑_{i=1}^n∑_{​j=1}^m∑_{x|i}∑_{y|j}[d|gcd(x,y)]\\ d=1min(n,m)μ(d)i=1nj=1mxiyj[dgcd(x,y)] 每 个 d 如 果 在 当 前 x , y 处 合 法 , 那 么 在 x , y 的 倍 数 处 也 一 定 合 法 , 即 每个d如果在当前x,y处合法,那么在x,y的倍数处也一定合法,即\\ dx,yx,y ∑ d = 1 m i n ( n , m ) μ ( d ) ∑ x = 1 n ∑ ​ y = 1 m [ d ∣ g c d ( x , y ) ] ⌊ n x ⌋ ⌊ m y ⌋ ∑_{d=1}^{min(n,m)}μ(d)∑_{x=1}^n∑_{​y=1}^m[d|gcd(x,y)]\lfloor\frac{n}{x}\rfloor\lfloor \frac{m}{y}\rfloor\\ d=1min(n,m)μ(d)x=1ny=1m[dgcd(x,y)]xnym [ d ∣ g c d ( x , y ) ] 的 意 义 即 为 x , y 的 公 因 数 [d|gcd(x,y)]的意义即为x,y的公因数 [dgcd(x,y)]x,y 下 面 进 行 枚 举 项 转 换 , 直 接 枚 举 倍 数 \\下面进行枚举项转换,直接枚举倍数\\ ∑ d = 1 m i n ( n , m ) μ ( d ) ∑ x = 1 n / d ∑ ​ y = 1 m / d ⌊ n d x ⌋ ⌊ m d y ⌋ 即 ∑_{d=1}^{min(n,m)}μ(d)∑_{x=1}^{n/d}∑_{​y=1}^{m/d}\lfloor\frac{n}{dx}\rfloor\lfloor \frac{m}{dy}\rfloor \\即 d=1min(n,m)μ(d)x=1n/dy=1m/ddxndym ∑ d = 1 m i n ( n , m ) μ ( d ) ( ∑ x = 1 n / d ⌊ n d x ⌋ ) ( ∑ ​ y = 1 m / d ⌊ m d y ⌋ ) ∑_{d=1}^{min(n,m)}μ(d)(∑_{x=1}^{n/d}\lfloor\frac{n}{dx}\rfloor)(∑_{​y=1}^{m/d}\lfloor \frac{m}{dy}\rfloor)\\ d=1min(n,m)μ(d)(x=1n/ddxn)(y=1m/ddym)
对 于 多 组 数 据 我 们 即 可 预 处 理 ∑ x = 1 n n x 提 高 速 率 对于多组数据我们即可预处理∑_{x=1}^{n}\frac{n}{x}提高速率 x=1nxn

#include<iostream>
#include<algorithm>
using namespace std;
#define N 50010
int T;
int mu[N],prim[N],cnt,k,g[N];
long long sum[N];
bool vis[N];

inline void get(int n){
    mu[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i]){//i为质数
            mu[i]=-1;prim[++cnt]=i;
        }
        for(int j=1;j<=cnt&&i*prim[j]<=n;j++)
        {
            vis[i*prim[j]]=1;
            if(i%prim[j]==0)break;//i*prim[j]指数的大于1
            else mu[i*prim[j]]=-mu[i];
        }
    }
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+(long long)mu[i];
    for(int i=1;i<=n;i++){
        long long ans=0;
        for(int l=1,r;l<=i;l=r+1){
            r=(i/(i/l));
            ans+=(r-l+1)*1ll*(i/l);
        }
        g[i]=ans;
    }
}

inline long long calc(int a,int b){
    int maxx;
    long long ans=0;
    maxx=min(a,b);
    for(int l=1,r;l<=maxx;l=r+1){
        r=min(a/(a/l),b/(b/l));
        ans+=1ll*g[a/l]*g[b/l]*(sum[r]-sum[l-1]);
    }
    return ans;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>T;
    get(N);
    while(T--){
        int a,b;
        cin>>a>>b;
        cout<<calc(a,b)<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值