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

HDU 4135 Co-prime(容斥:二进制解法)题解

时间:2018-08-30 14:25:34      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:进制   题解   lse   ==   name   区间   inf   can   bsp   

题意:给出[a,b]区间内与n互质的个数

思路:如果n比较小,我们可以用欧拉函数解决,但是n有1e9。要求区间内互质,我们可以先求前缀内互质个数,即[1,b]内与n互质,求互质,可以转化为求不互质,也就是有除1的公因数。那么我们把n质因数分解,就能算出含某些公因数的不互质的个数。因为会重复,所以容斥解决。因为因数个数可能很多(随便算了一个20!> 2e18,所以质因数分解个数不会超过20个),我们可以用二进制来遍历解决。

#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 20000 + 10;
const int seed = 131;
const int MOD = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
ll y[5000], cnt;
ll a, b, n;
ll solve(ll num){
    ll sum = 0, val, tot;
    for(ll i = 1; i < (1 << cnt); i++){ //这里是小于最多只能cnt位
        val = 1;
        tot = 0;
        for(ll j = 0; j < cnt; j++){
            if(i & (1 << j)){   //第j个因子被用到
                val *= y[j];
                tot++;
            }
        }
        if(tot & 1){
            sum += num / val;
        }
        else{
            sum -= num / val;
        }
    }
    return num - sum;
}
int main(){
    int T, Case = 1;
    scanf("%d", &T);
    while(T--){
        scanf("%lld%lld%lld", &a, &b, &n);
        cnt = 0;
        ll x = n;
        for(ll i = 2; i * i <= x; i++){
            if(x % i == 0){
                y[cnt++] = i;
                while(x % i == 0){
                    x /= i;
                }
            }
        }
        if(x > 1){
            y[cnt++] = x;
        }
        printf("Case #%d: %lld\n", Case++, solve(b) - solve(a - 1));
    }
    return 0;
}

 

HDU 4135 Co-prime(容斥:二进制解法)题解

标签:进制   题解   lse   ==   name   区间   inf   can   bsp   

原文地址:https://www.cnblogs.com/KirinSB/p/9559724.html

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