zoukankan      html  css  js  c++  java
  • BZOJ 1101: [POI2007]Zap

    二次联通门 : BZOJ 1101: [POI2007]Zap

    二次联通门 :  luogu P3455 [POI2007]ZAP-Queries

     求下面式子的值

    因为 x∈[1,a], y∈[1,b]

    那么 x/k∈[1,a/k], y/k∈[1,b/k]

    则有以下式子

    因为

    所以

    我们把 μ(i)  放到前面去, 交换一下枚举的顺序得到以下的式子

    这个式子就变成这样了

     因为有这只有种取值

    所以下底函数分块,前缀和优化下就能过了。

     弃了弃了。。。果然自己太笨。。反演看一上午看不明白。。

    /*
        BZOJ 1101: [POI2007]Zap
        
        莫比乌斯反演
        
        
    */
    #include <cstdio>
    
    void read (int &now)
    {
        register char word = getchar ();
        bool temp = false;
        for (now = 0; word < '0' || word > '9'; word = getchar ());
        for (; word >= '0' && word <= '9'; now = now * 10 + word - '0', word = getchar ());
    }
    
    inline void swap (int &a, int &b)
    {
        int now = a;
        a = b;
        b = now;
    }
    
    inline int min (int a, int b)
    {
        return a < b ? a : b;
    }
    
    #define Max 100005
    
    bool is_prime[Max];
    int prime_list[Max];
    
    int mobius[Max];
    
    int sum[Max];
    
    void Euler_to_Mobius (int N)
    {
        is_prime[0] = is_prime[1] = true;
        mobius[1] = 1;
        int Prime_Count = 0;
        for (register int i = 2, j, pos; i <= N; i ++)
        {
            if (!is_prime[i])
            {
                prime_list[++ Prime_Count] = i;
                mobius[i] = -1;
            }
            for (j = 1; j <= Prime_Count && i * prime_list[j] <= N; j ++)
            {
                pos = i * prime_list[j];
                is_prime[pos] = true;
                if (i % prime_list[j])
                    mobius[pos] = -mobius[i];
                else
                {
                    mobius[pos] = 0;
                    break;
                }    
            }
        }
    }
    
    
    int main (int argc, char *argv[])
    {
        int T;
        read (T);
        int _Limit = Max - 2;
        Euler_to_Mobius (_Limit);
        
        for (int i = 1; i <= _Limit; i ++)
            sum[i] = sum[i - 1] + mobius[i];
        
        long long Answer = 0;
        
        for (int x, y, z; T --; Answer = 0)
        {
            read (x);
            read (y);
            read (z);
            
            x /= z;
            y /= z;
    
            if (x > y) 
                swap (x, y);
            for (register int j = 0, i = 1; i <= x; i = j + 1)
            {
                j = min (x / (x / i), y / (y / i));
                Answer += 1LL * (sum[j] - sum[i - 1]) * (x / i) * (y / i);
            }
            
            printf ("%lld
    ", Answer);
        }
        
        return 0;
    }
  • 相关阅读:
    软件工程第二次作业
    软件工程第一次作业
    5T-时延小结
    4T--5G网络时延
    2T--网络切片
    1T--5G 三大应用场景
    2020软件工程第一次作业
    软件工程最后一次作业
    软件工程第四次作业
    软件工程第三次作业
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/7201426.html
Copyright © 2011-2022 走看看