• [HAOI 2011] Problem b


    [题目链接]

            https://www.lydsy.com/JudgeOnline/problem.php?id=2301

    [算法]

             首先,满足a <= x <= b , c <= y <= d , GCD(x,y) = k的二元组对数可以转化为求 :

             1 <= x <= b , 1 <= y <= d , GCD(x,y) = k的二元组对数 

             -  1 <= x <= (a - 1) , 1 <= y <= d , GCD(x,y) = k的二元组对数

             - 1 <= x <= b , 1 <= y <= (c - 1) , GCD(x,y) = k的二元组对数

             + 1 <= x <= (a - 1) , 1 <= y <= (c - 1) , GCD(x,y) = k的二元组对数

             可以通过莫比乌斯函数 + 容斥原理解决 , 并用数论分块加速

             时间复杂度 : O(T ( sqrt(A) + sqrt(B) ) ( 其中,sqrt表示开根号)

    [代码]

            

    #include<bits/stdc++.h>
    using namespace std;
    #define MAXN 50010
    
    int T,a,b,c,d,k;
    int miu[MAXN],sum[MAXN];
    
    inline void sieve()
    {
            static bool visited[MAXN];
            for (int i = 1; i < MAXN; i++) 
            {
                    visited[i] = false;
                    miu[i] = 1;
            }
            for (int i = 2; i < MAXN; i++)
            {
                    if (visited[i]) continue;
                    miu[i] = -1;
                    for (int j = 2 * i; j < MAXN; j += i)
                    {
                            visited[j] = true;
                            if ((j / i) % i == 0) miu[j] = 0;
                            else miu[j] *= -1;
                    }        
            }    
            for (int i = 1; i < MAXN; i++) sum[i] = sum[i - 1] + miu[i];
    }
    inline int getsum(int l,int r)
    {
        return sum[r] - sum[l - 1];
    }
    inline int solve(int x,int y)
    {
            int gi;
            int ret = 0;
            for (int i = 1; i <= min(x,y); i = gi + 1)
            {
                    gi = min((x / (x / i)),(y / (y / i)));
                    ret += (x / i) * (y / i) * getsum(i,gi);        
            }    
            return ret;
    }
    
    int main() 
    {
            
            sieve();
            scanf("%d",&T);
            while (T--)
            {
                    scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
                    printf("%d
    ",solve(b / k,d / k) - solve((a - 1) / k,d / k) - solve(b / k,(c - 1) / k) + solve((a - 1) / k,(c - 1) / k));
            }
            
            return 0;
        
    }
  • 相关阅读:
    GetEnumName 枚举名称 字符串
    拖拽文件
    小米手机Root 刷机
    微软语言 中文 英文 中英文
    MTP
    MD5加密算法全解析
    ORA-28000: the account is locked
    HTTP状态码
    HTTP 消息结构
    @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • 原文地址:https://www.cnblogs.com/evenbao/p/9581165.html
Copyright © 2020-2023  润新知