• 《洛谷P2522 [HAOI2011]Problem b》


    一段时间没做又不太会推了。

    首先这题需要一个容斥的做法。

    ans = solve(b,d) - solve(a - 1,d) - solve(b,c - 1) + solve(a - 1,c - 1) //这个非常容易推出。

    然后就是单个的计算了。

     

    $sum_{i = 1}^{n} sum_{j = 1}^{m}|gcd(i,j) = k| ightarrow sum_{i = 1}^{[frac{n}{k}]} sum_{j = 1}^{[frac{m}{j}]}|gcd(i,j) = 1| ightarrow sum_{i = 1}^{[frac{n}{k}]} sum_{j = 1}^{[frac{m}{j}]} sum_{d | gcd(i,j)}^{}mu(d) ightarrow sum_{d = 1}^{min([frac{n}{k}],[frac{m}{j}])}mu (d)~ [frac{n}{kd}]~[frac{m}{kd}]$

    看成n / k / d,,m / k / d整除分块即可。

     

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 5e4+5;
    const int M = 1e7+5;
    const LL Mod = 1e9+7;
    #define pi acos(-1)
    #define INF 1e9
    #define CT0 cin.tie(0),cout.tie(0)
    #define IO ios::sync_with_stdio(false)
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline int read()
        {
            int x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}
            return x * f;
        }
        void print(int x){
            if(x < 0){x = -x;putchar('-');}
            if(x > 9) print(x/10);
            putchar(x%10+'0');
        }
    }
    using namespace FASTIO;
    
    int a,b,c,d,k;
    int prime[N],tot = 0,mu[N];
    LL sum[N];
    bool vis[N];
    void init()
    {
        mu[1] = 1;
        for(int i = 2;i < N;++i)
        {
            if(!vis[i])
            {
                prime[++tot] = i;
                mu[i] = -1;
            }
            for(int j = 1;j <= tot && i * prime[j] < N;++j)
            {
                vis[i * prime[j]] = 1;
                if(i % prime[j] == 0) break;
                mu[i * prime[j]] = -mu[i];
            }
        }
        for(int i = 1;i < N;++i) sum[i] = sum[i - 1] + mu[i];
    }
    LL solve(int n,int m)
    {
        n = n / k,m = m / k;
        LL ans = 0;
        for(int L = 1,r = 0;L <= min(n,m);L = r + 1)
        {
            r = min(n / (n / L),m / (m / L));
            ans += (sum[r] - sum[L - 1]) * (n / L) * (m / L);
        }
        return ans;
    }
    int main()
    {
        init();
        int ca;ca = read();
        while(ca--)
        {
            a = read(),b = read(),c = read(),d = read(),k = read();
            LL ans = solve(b,d) - solve(a - 1,d) - solve(b,c - 1) + solve(a - 1,c - 1);
            printf("%lld
    ",ans);
        }
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    poj 1035 字符串匹配
    拓扑排序的小总结
    POJ1018
    POJ1328详细题解
    POJ1159题解报告
    POJ1088 (滑雪)
    树状树组区间修改,单点修改模板
    spfa模板
    树状树组离散化求逆序对模板
    POJ3723(最小生成树,负权)
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13882644.html
Copyright © 2020-2023  润新知