GCD HDU - 1695(容斥原理)

要求从满足gcd(x, y) = k的对数,其中x属于[1, n], y属于[1, m]

gcd(x, y) = k

==>gcd(x/k, y/k) =1

x/k属于[1, n/k], y/k属于[1, m/k]

又因为对数不可以重复,所以我可以限制对于gcd(x, y)中,让y>=x,这样就不会重复了,然后问题转化成了对于[1, n/k]区间内的每一个 i ,求 i 与 [i,m]中的数互质的对数,然后对于每一个 i 的答案相加求和

#include<map>
#include<set>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lowbit(x) (x & (-x))
#define INOPEM freopen("in.txt", "r", stdin)
#define OUTOPEN freopen("out.txt", "w", stdout)

typedef unsigned long long int ull;
typedef long long int ll;
const double pi = 4.0*atan(1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 1e5+50;
const int maxm = 1e9+10;
const int mod = 1e9+7;
using namespace std;

int n, m;
int T, tol;
bool pri[maxn];
vector<int> vec[maxn];

void handle() {
    memset(pri, true, sizeof pri);
    for(int i=2; i<maxn; i++) {
        if(pri[i]) {
            vec[i].push_back(i);
            for(int j=2; i*j<maxn; j++) {
                vec[i*j].push_back(i);
                pri[i*j] = false;
            }
        }
    }
}

ll solve(ll x, int k) {
    ll ans = 0;
    int len = vec[k].size();
    for(int i=1; i<(1<<len); i++) {
        int cnt = 0;
        ll tmp = 1;
        for(int j=0; j<len; j++) {
            if(i & (1<<j)) {
                cnt++;
                tmp *= vec[k][j];
            }
        }
        if(cnt & 1)    ans += x / tmp;
        else        ans -= x / tmp;
    }
    return ans;
}

int main() {
    handle();
    int cas = 1;
    int T;
    scanf("%d", &T);
    while(T--) {
        int a, b, k;
        scanf("%d%d%d%d%d", &a, &n, &b, &m, &k);
        if(k == 0) {
            printf("Case %d: 0\n", cas++);
            continue;
        }
        n /= k, m /= k, k = 1;
        if(n > m)    swap(n, m);
        ll ans = 0;
        //[i, m]
        for(int i=1; i<=n; i++) {
            ans += 1ll * (m-i+1) - 1ll * (solve(m, i) - solve(1ll * (i-1), i));
        }
        printf("Case %d: %I64d\n", cas++, ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/H-Riven/p/9530573.html

时间: 2024-08-09 06:25:29

GCD HDU - 1695(容斥原理)的相关文章

GCD HDU - 1695 (容斥原理)

GCD HDU - 1695 题意:给你5个数a,b,c,d,k.x属于[a,b]y属于[c,d]. 问你有多少对(x,y)的公约数为k.  注意(x,y)和 (y,x)视为同一对,a和c为1. 通过b/k,d/k,等价于把区间除以k,那么就变成了求有多少对(x,y)互素. 欧拉函数+容斥原理. 注意k可能为0. 1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int maxn=1

hdu 1695 容斥原理或莫比乌斯反演

GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5310    Accepted Submission(s): 1907 Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y)

HDU 1695 GCD 欧拉函数+容斥原理+质因数分解

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695 题意:在[a,b]中的x,在[c,d]中的y,求x与y的最大公约数为k的组合有多少.(a=1, a <= b <= 100000, c=1, c <= d <= 100000, 0 <= k <= 100000) 思路:因为x与y的最大公约数为k,所以xx=x/k与yy=y/k一定互质.要从a/k和b/k之中选择互质的数,枚举1~b/k,当选择的yy小于等于a/k时,可以

HDU 1695 GCD (数论-整数和素数,组合数学-容斥原理)

GCD Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k. GCD(x, y) means the greatest common divisor of x and y. Since the number of choices may be very large, you're only required to output t

HDU 1695(GCD)

GCD Time Limit: 3000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u [Submit]   [Go Back]   [Status] Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k. GCD(x, y) means the greatest common

hdu 1695 莫比乌斯反演

hdu 1695 莫比乌斯反演 题意: 给出a,b,c,d,k, 求满足a <= x <= b && c <= y <= d && gcd(x,y)=k 的数对(x,y)的对数. 限制: a=c=1; 0 < b,c <= 1e5; (n1,n2) 和 (n2,n1) 算为同种情况 思路: 其实是求满足1 <= x <= b/k && 1 <= y <= d/k && gcd(x,y

hdu 1695 GCD(欧拉函数+容斥原理)

http://acm.hdu.edu.cn/showproblem.php? pid=1695 非常经典的题.同一时候感觉也非常难. 在区间[a,b]和[c,d]内分别随意取出一个数x,y,使得gcd(x,y) = k.问这种(x,y)有多少对.能够觉得a,c均为1,并且gcd(5,7)与gcd(7,5)是同一种. 由于gcd(x,y) = k,那么gcd(x/k,y/k) = 1.也就是求区间[1,b/k]和[1,d/k]内这种(x,y)对使得gcd(x,y) = 1. 为了防止计数反复,首先

HDU 1695 GCD(欧拉函数+容斥原理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695 题意:x位于区间[a, b],y位于区间[c, d],求满足GCD(x, y) = k的(x, y)有多少组,不考虑顺序. 思路:a = c = 1简化了问题,原问题可以转化为在[1, b/k]和[1, d/k]这两个区间各取一个数,组成的数对是互质的数量,不考虑顺序.我们让d > b,我们枚举区间[1, d/k]的数i作为二元组的第二位,因为不考虑顺序我们考虑第一位的值时,只用考虑小于i的情

HDU 1695 GCD (容斥原理+质因数分解)

先进行预处理,对每一个数分解质因数. 然后将因为若gcd(x,y)==z,那么gcd(x/z,y/z)==1,又因为不是z的倍数的肯定不是,所以不是z的倍数的可以直接去掉,所以只要将b和d除以k,然后就转化成了求两个范围中互质的对数了.这时候可以枚举1~b,然后用容斥原理找1~d范围内的与枚举数互质的数的个数,为了避免重复,只要再限定下大小关系就可以了,具体见代码. 代码如下: #include <iostream> #include <string.h> #include <