HDU 4135 Co-prime(容斥:二进制解法)题解
Posted kirinsb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4135 Co-prime(容斥:二进制解法)题解相关的知识,希望对你有一定的参考价值。
题意:给出[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 ", Case++, solve(b) - solve(a - 1)); } return 0; }
以上是关于HDU 4135 Co-prime(容斥:二进制解法)题解的主要内容,如果未能解决你的问题,请参考以下文章