您的位置:首页 > 其它

[HDOJ4135]Co-prime

2015-08-17 15:08 357 查看
题目链接: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 << "Case #" << kase++ << ": " << r - l << endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: