zoukankan      html  css  js  c++  java
  • 洛谷3327:约数个数和

    洛谷3327:约数个数和

    题意描述:

    • (d(x))(x)的约数个数,给定(n,m)求:
    • (sum_{i=1}^nsum_{j=1}^md(ij))(T)组数据。
    • 数据范围(T,n,mleq 50000).

    思路

    • (d(ij)=sum_{x|i}sum_{y|j}[gcd(x,y)=1]).
    • 所求就为:
    • (sum_{i=1}^nsum_{j=1}^msum_{x|i}sum_{y|j}[gcd(x,y)=1])
    • 枚举(x,y)有:
    • (sum_{x=1}^nsum_{y=1}^m[gcd(x,y)=1]sum_{i=1}^nsum_{j=1}^m[x|n and y|m]).
    • (sum_{x=1}^nsum_{y=1}^m[gcd(x,y)=1]frac{n}{x}frac{m}{y})
    • 修改一下变量吧...:
    • (sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=1]frac{n}{i}frac{m}{j}).
    • 开始反演:
    • (f(x)=sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=x]frac{n}{i}frac{m}{j}).
    • 按照套路有:
    • (F(x)=sum_{x|d}f(d)=sum_{i=1}^nsum_{j=1}^mfrac{n}{i}frac{m}{j}[x|gcd(i,j)])
    • 枚举(ix,jx),有
    • (=sum_{i=1}^{frac{n}{x}}sum_{j=1}^{frac{m}{x}}frac{n}{ix}frac{m}{jx}).
    • 这样就可以不用理会(gcd(i,j))这个条件。
    • 有反演公式:
    • (f(x)=sum_{x|d}mu(frac{d}{x})F(d)).
    • 又知道(ans=f(1))
    • (=sum_{1|d}mu(d)F(d))
    • (=sum_{d=1}^{min(n,m)}mu(d)sum_{i=1}^{n/d}frac{n}{di}sum_{j=1}^{m/d}frac{m}{dj}).
    • 到了这里其实就可以做了,但是还有个小问题,就是如何快速的计算(sum_{i=1}^nfrac{n}{i})
    • 可以用整除分块来处理。
    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    typedef long long ll;
    const int maxn = 5e4 + 10;
    int T, n, m;
    
    bool vis[maxn];
    int primes[maxn], mu[maxn], cnt, sum[maxn];
    ll s[maxn];
    void get_mu(int n)
    {
        mu[1] = 1;
        for(int i = 2; i <= n; i++)
        {
            if(!vis[i])
            {
                primes[++cnt] = i;
                mu[i] = -1;
            }
            for(int j = 1; primes[j] <= n/i; j++)
            {
                vis[primes[j]*i] = 1;
                if(i % primes[j] == 0) break;
                else mu[i*primes[j]] = -mu[i];
            }
        }
        for(int i = 1; i <= n; i++)
            sum[i] = sum[i-1] + mu[i];
        for(int i = 1; i <= n; i++)
        {
            ll res = 0;
            for(int l = 1, r; l <= i; l = r + 1)
            {
                r = i/(i/l);
                res += 1ll*(r-l+1)*1ll*(i/l);
            }
            s[i] = res;
        }
    }
    
    inline void solve(int n, int m)
    {
        if(n > m) swap(n, m);
        ll ans = 0;
        for(int l = 1, r; l <= n; l = r+1)
        {
            r = min(n/(n/l), m/(m/l));
            ans += 1ll*(sum[r]-sum[l-1])*1ll*s[n/l]*1ll*s[m/l];
        }
        printf("%lld
    ", ans);
    }
    
    signed main()
    {
        get_mu(50000);
        scanf("%lld", &T);
        while(T--)
        {
            scanf("%lld%lld", &n, &m);
            solve(n, m);
        }
        return 0;
    }
    
    
  • 相关阅读:
    bfs,队列
    Wannafly挑战赛22 A计数器(裴蜀定理 gcd)
    素数筛模板
    HDU
    HDU
    控制精度-----直接截取,不需四舍五入
    jstl下载与配置
    B. Treasure Hunt
    动态数组vector
    Manacher算法
  • 原文地址:https://www.cnblogs.com/zxytxdy/p/12173434.html
Copyright © 2011-2022 走看看