hdu 1695 GCD 欧拉函数 + 容斥

http://acm.hdu.edu.cn/showproblem.php?pid=1695

要求[L1, R1]和[L2, R2]中GCD是K的个数。那么只需要求[L1, R1 / K]  和 [L2, R2 / K]中GCD是1的对数。

由于(1, 2)和(2, 1)是同一对。

那么我们枚举大区间,限制数字一定是小于等于枚举的那个数字就行。

比如[1, 3]和[1, 5]

我们枚举大区间,[1, 5],在[1, 3]中找互质的时候,由于又需要要小于枚举数字,那么直接上phi

对于其他的,比如4这样,在[1, 3]中找有多少个数字和它互质。

这需要容斥。先求不互质的个数,因为有个明显的道理,12 = 2 * 2 * 3,那么2的倍数可以排除,3的倍数可以排除,但是排除多了一部分。

区间中与i不互质的个数 = (区间中i的每个质因数的倍数个数)-(区间中i的每两个质因数乘积的倍数)+(区间中i的每3个质因数的成绩的倍数个数)-(区间中i的每4个质因数的乘积)

这个容斥好想但是不好写。我的dfs写的很烂。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 100000 + 20;
int prime[maxn];//这个记得用int,他保存的是质数,可以不用开maxn那么大
bool check[maxn];
int total;
bool is_prime[maxn];
int his[maxn][50 + 20];
int Size[maxn];
void initprime() {
    for (int i = 2; i <= maxn - 20; i++) {
        if (!check[i]) { //是质数了
            prime[++total] = i; //只能这样记录,因为后面要用
            is_prime[i] = true;
        }
        for (int j = 1; j <= total; j++) { //质数或者合数都进行的
            if (i * prime[j] > maxn - 20) break;
            check[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
            //关键,使得它只被最小的质数筛去。例如i等于6的时候。
            //当时的质数只有2,3,5。6和2结合筛去了12,就break了
            //18留下等9的时候,9*2=18筛去
        }
    }
//    Size[1] = 1;
//    his[1][1] = 1;
    for (int i = 1; i <= maxn - 20; ++i) {
        if (is_prime[i]) {
            Size[i] = 1;
            his[i][1] = i;
            continue;
        }
        int t = i;
        for (int j = 1; j <= total; ++j) {
            if (prime[j] > t) break;
            if (t % prime[j] == 0) {
                his[i][++Size[i]] = prime[j];
                t /= prime[j];
                while (t % prime[j] == 0) {
                    t /= prime[j];
                }
            }
        }
    }
    return ;
}
int phi[maxn];
void init_phi() {
    phi[1] = 1;
    for (int i = 2; i <= maxn - 20; i++) {
        if (!phi[i]) {
            for (int j = i; j <= maxn - 20; j += i) {
                if (!phi[j]) phi[j] = j;
                phi[j] = phi[j] / i * (i - 1);
            }
        }
    }
    return ;
}
LL calc(int up, int cur, int number, int tobuild, int flag) {
    LL ans = 0;
    for (int i = cur; i <= Size[number]; ++i) {
        if (flag == 0) {
            ans += up / (his[number][i] * tobuild) + calc(up, i + 1, number, tobuild * his[number][i], !flag);
        } else ans += -up / (his[number][i] * tobuild) + calc(up, i + 1, number, tobuild * his[number][i], !flag);
    }
    return ans;
}
int f;
void work() {
    int L1, R1, L2, R2, k;
    scanf("%d%d%d%d%d", &L1, &R1, &L2, &R2, &k);
    if (k == 0) {
        printf("Case %d: 0\n", ++f);
        return;
    }
    R1 /= k;
    R2 /= k;
    if (R1 < R2) swap(R1, R2);
    LL ans = 0;
    for (int i = 1; i <= R2; ++i) {
        ans += phi[i];
    }
    for (int i = R2 + 1; i <= R1; ++i) {
        ans += R2 - calc(R2, 1, i, 1, 0);
    }
    printf("Case %d: %I64d\n", ++f, ans);
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    initprime();
    init_phi();
//    cout << 24 - calc(24, 1, 12, 1, 0) << endl;
//    cout << 12 - calc(12, 1, 12, 1, 0) << endl;
//    for (int i = 1; i <= Size[10]; ++i) {
//        printf("%d ", his[10][i]);
//    }
    int t;
    scanf("%d", &t);
    while (t--) {
        work();
    }
    return 0;
}

时间: 2024-08-05 04:12:13

hdu 1695 GCD 欧拉函数 + 容斥的相关文章

hdu 1695 GCD 欧拉函数+容斥

题意:给定a,b,c,d,k x属于[1 , c],y属于[1 , d],求满足gcd(x,y)=k的对数.其中<x,y>和<y,x>算相同. 思路:不妨设c<d,x<=y.问题可以转化为x属于[1,c / k ],y属于[1,d/k ],x和y互质的对数. 那么假如y<=c/k,那么对数就是y从1到c/k欧拉函数的和.如果y>c/k,就只能从[ c/k+1 , d ]枚举,然后利用容斥.详见代码: /****************************

HDU 1695 GCD 欧拉函数+容斥定理

输入a b c d k求有多少对x y 使得x在a-b区间 y在c-d区间 gcd(x, y) = k 此外a和c一定是1 由于gcd(x, y) == k 将b和d都除以k 题目转化为1到b/k 和1到d/k 2个区间 如果第一个区间小于第二个区间 讲第二个区间分成2部分来做1-b/k 和 b/k+1-d/k 第一部分对于每一个数i 和他互质的数就是这个数的欧拉函数值 全部数的欧拉函数的和就是答案 第二部分能够用全部数减去不互质的数 对于一个数i 分解因子和他不互质的数包括他的若干个因子 这个

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(欧拉函数+容斥原理)

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 2588 GCD (欧拉函数)

GCD Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1013    Accepted Submission(s): 457 Problem Description The greatest common divisor GCD(a,b) of two positive integers a and b,sometimes writt

hdu 6390 欧拉函数+容斥(莫比乌斯函数) GuGuFishtion

http://acm.hdu.edu.cn/showproblem.php?pid=6390 题意:求一个式子 题解:看题解,写代码 第一行就看不出来,后面的sigma公式也不会化简.mobius也不会 就自己写了个容斥搞一下(才能维持现在的生活) //别人的题解https://blog.csdn.net/luyehao1/article/details/81672837 #include <iostream> #include <cstdio> #include <cstr

hdu1695(莫比乌斯)或欧拉函数+容斥

题意:求1-b和1-d之内各选一个数组成数对,问最大公约数为k的数对有多少个,数对是有序的.(b,d,k<=100000) 解法1: 这个可以简化成1-b/k 和1-d/k 的互质有序数对的个数.假设b=b/k,d=d/k,b<=d.欧拉函数可以算出1-b与1-b之内的互质对数,然后在b+1到d的数i,求每个i在1-b之间有多少互质的数.解法是容斥,getans函数参数的意义:1-tool中含有rem位置之后的i的质因子的数的个数. 在 for(int j=rem;j<=factor[i

HDU1695-GCD(数论-欧拉函数-容斥)

GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5454    Accepted Submission(s): 1957 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

GuGuFishtion HDU - 6390 (欧拉函数,容斥)

GuGuFishtion \[ Time Limit: 1500 ms\quad Memory Limit: 65536 kB \] 题意 给出定义\(Gu(a, b) = \frac{\phi(ab)}{\phi(a)\phi(b)}\) 求出\(\sum_{a=1}^{m}\sum_{b=1}^{n}Gu(a,b) (mod p)\) 思路 首先对于欧拉函数,我们知道欧拉函数的朴素式子为:\(\phi(n) = n*(1-\frac{1}{p1})*(1-\frac{1}{p2}) * ..