HLG 1807 噢啦 (欧拉函数)

链接: http://acm.hrbust.edu.cn/index.php?

m=ProblemSet&a=showProblem&problem_id=1807

Description
上个星期,小胖子学会了欧拉函数,他得意的说:”在a和b之间有多少个与c互素的数字,这种简单题用欧拉就哦啦。“
但是这次三三又问小胖子。在a和b之间有多少个与c互素的数。

Input
第一行包含一个整数t,代表測试次数(1<=1000)。

接下来每一组測试次数输入a。b,c。满足(1<=a<=b<=10^15,1<=c<=10^9)。

Output
对于每组測试输出结果。占一行。
Sample Input
2

1 10 2

3 15 5

Sample Output
5

10


代码及解析例如以下:(数据范围好大)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstdlib>
using namespace std;

typedef long long LL;
LL a, b, n;
vector <long long> vt;

LL solve(LL x, LL n)
{
    vt.clear();
    for(LL i=2; i*i<=n; i++) {   //对n进行素数分解
        if(n%i == 0) {
            vt.push_back(i);
            while(n%i == 0) n /= i;
        }
    }
    if(n > 1) vt.push_back(n);
    LL sum = 0, val, cnt;
    for(LL i=1; i<(1<<vt.size()); i++) {  //用二进制来1,0来表示第几个素因子是否被用到,如m=3,三个因子是2,3,5。则i=3时二进制是011,表示第2、3个因子被用到
        val = 1, cnt = 0;
        for(LL j=0; j<vt.size(); j++) {
            if(i & (1<<j)) {       //推断第几个因子眼下被用到
                val *= vt[j];
                cnt++;
            }
        }
        if(cnt & 1) sum += x/val;      //容斥原理,奇加偶减
        else sum -= x/val;
    }
    return x-sum;
}

int main()
{
    int cas;
    scanf("%d", &cas);
    while(cas--) {
        cin >> a >> b >> n;
        cout << solve(b, n) - solve(a-1, n) << endl;
    }
    return 0;
}



原文地址:https://www.cnblogs.com/wgwyanfs/p/6895925.html