hdu 4135 Co-prime (组合数学:容斥定理+欧拉函数)

来源:互联网 发布:win32 api 知乎 编辑:程序博客网 时间:2024/05/20 18:53

给定a, b, n

找到a,b范围内与n互质的数

我的方法是用欧拉函数求出n的唯一分解式

唯一分解式中对应素数在a,b范围内的倍数均与n不互质

求出倍数的个数,再用总数减去这些倍数的个数即可

但是对于1, 10, 6

6=2×3,因为2,3的倍数有6重复出现,所以要用到容斥定理10-(10/2-1/2)-(10/3-1/3)+(10/6-1/6)

这道题还有一个要注意的地方就是使用(b/tmp-a/tmp)求a-b范围内tmp倍数的个数时需要考虑a%tmp==0的情况

如输入:4, 10, 2

该范围内与2不互质的数应该有(4,6,8,10)四个

而(b/tmp-a/tmp)==(10/2-4/2)==3个

所以应该判断如果a%tmp==0,该等式的结果++

0ms代码如下:

//#include <bits/stdc++.h>#include <vector>#include <cstdio>#include <iostream>#define LL long longusing namespace std;LL ans;vector<int> vec;LL gcd(LL a, LL b) {    return b ? gcd(b, a%b) : a;}void euler_phi(int n) {    vec.clear();    for(int i=2; i*i<=n&&n>1; ++i) {        while(n%i == 0) {            vec.push_back(i);            n /= i;            while(n % i == 0)                n /= i;        }    }    if(n > 1)        vec.push_back(n);    return ;}void dfs(LL a, LL b, LL w, int i, int k) {    for( ; i<vec.size(); ++i) {        if(vec[i]) {            LL tmp = w/gcd(w, vec[i])*vec[i];            //printf("tmp = %d\n", tmp);            ans += k*(b/tmp-a/tmp);            if(a%tmp == 0)                ans += k;            dfs(a, b, tmp, i+1, -k);        }    }}int main(void) {    int T, n;    LL a, b;    scanf("%d", &T);    for(int t=1; t<=T; ++t) {        cin >> a >> b >> n;        ans = 0;        ans += b-a+1;        euler_phi(n);        dfs(a, b, 1, 0, -1);        printf("Case #%d: ", t);        cout << ans << endl;    }}


0 0
原创粉丝点击