码迷,mamicode.com
首页 > 其他好文 > 详细

[HDOJ4135]Co-prime

时间:2015-08-17 15:26:52      阅读:102      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4135

题意:给一个区间[a,b],再给你一个数n,求在这个区间[a,b]中与n互质的数的个数。

思路:这是一道数学题,如果数据范围不大的话可以直接套用欧拉函数,但是数据范围给得很大。所以用容斥原理来做。

具体思路就是计算[1,a]中与n非互质的数的个数以及[1,b]中与n非互质的数的个数,然后用上限减掉非互质的数的个数,之后作差即可。首先分解n的质因数,接着用一个变量的二进制表示质因数中1的数量,当这个变量是偶数的时候就加,奇数的话就减,因为重复计算了(详解见书《挑战程序设计竞赛P297》)。代码如下:

技术分享
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>

using namespace std;
typedef long long LL;

vector<LL> v;
LL a, b;
LL n;

void init() {
    v.clear();
    scanf("%I64d %I64d %I64d", &a, &b, &n);
    LL nn = (LL)sqrt(n) + 1;
    for(int i = 2; i < nn; i++) {
        if(n % i == 0) {
            v.push_back(i);
            while(n % i == 0) {
                n /= i;
            }
        }
    }
    if(n > 1) {
        v.push_back(n);
    }
}

LL solve(LL x, LL y) {
    LL ans;
    LL m ,cnt;
    LL s = 1 << v.size();
    for(int i = 1; i < s; i++) {
        m = 1;
        cnt = 0;
        for(int j = 0; j < v.size(); j++) {
            if(i & (1 << j)) {
                m *= v[j];
                cnt++;
            }
        }
        if(cnt & 1) {
            ans += x / m;
        }
        else {
            ans -= x / m;
        }
    }
    return x - ans;
}
int main() {
    int t;
    int kase = 1;
    scanf("%d", &t);
    while(t--) {
        init();
        LL l, r;
        l = solve(a-1, n);
        r = solve(b, n);
        cout << l << " " << r;
        cout << "Case #" << kase++ << ": " << r - l << endl;
    }
}
View Code

 

[HDOJ4135]Co-prime

标签:

原文地址:http://www.cnblogs.com/vincentX/p/4736656.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!