hdu 4135 Co-prime (素数打表+容斥原理)
Posted ghzz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 4135 Co-prime (素数打表+容斥原理)相关的知识,希望对你有一定的参考价值。
题目链接
题意:问从A到B中与N互素的个数。
题解:
利用容斥原理:先求出与n互为素数的个数。
可以先将 n 进行素因子分解,然后用区间 x 除以 素因子,就得到了与 n 的 约数是那个素因子的个数,然后每次这样求一遍,但是发现有重 复的:举个例子 [1,10] 区间中与 6 互素的个数,应该是 10?(10/2+10/3)+(10/6)
然后利用二进制枚举子集个数,奇数加偶数减。
具体看代码:
#include <stdio.h> #include <cstring> #include <cmath> #include <iostream> #include <queue> #include <map> #include <list> #include <utility> #include <set> #include <algorithm> #include <deque> #include <iomanip> #include <vector> #define mem(arr, num) memset(arr, 0, sizeof(arr)) #define _for(i, a, b) for (int i = a; i <= b; i++) #define __for(i, a, b) for (int i = a; i >= b; i--) #define IO \ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); using namespace std; typedef long long ll; typedef vector<int> vi; const ll INF = 0x3f3f3f3f; const int mod = 1e9 + 7; const int N = 20 + 5; const int maxn = 1000000+5; bool vis[maxn+1000000]; int fac[maxn/100+5]; int prime[maxn],n; int num = 0; void getprime() { memset(vis, false, sizeof(vis)); for (int i = 2; i <= maxn; ++i) { if ( !vis[i] ) prime[++num] = i; for (int j = 1; j <= num && i * prime[j] <= n; j++) { vis[ i * prime[j] ] = true; if (i % prime[j] == 0) break; } } } int cnt = 0; void f(ll x) { cnt = 0; for(int i = 1; prime[i]*prime[i] <=x && i <=num; i++) { if(x%prime[i]==0){ fac[++cnt] = prime[i]; while(x%prime[i]==0) x /= prime[i]; } } if(x > 1) fac[++cnt] = x; } ll solve(ll x) { //利用二进制处理子集,奇数加偶数减。 ll ans = 0; for(int i = 1; i < ((ll)1 << cnt); i++) { int tmp = 1,sum = 0; for(int j = 0; j < cnt;j++){ if(i&((ll)1<<j))sum++, tmp *= fac[j+1]; } if(sum&1) ans += x/tmp; else ans -= x/tmp; } return ans; } int main() { int T; ll ans = 0,A,B,N; scanf("%d",&T); getprime(); for(int i = 1; i <= T; i++){ scanf("%lld%lld%lld",&A,&B,&N); f(N); ans = B - solve(B) - ((A - 1) - solve(A-1)); printf("Case #%d: %lld\n",i,ans); } return 0; }
以上是关于hdu 4135 Co-prime (素数打表+容斥原理)的主要内容,如果未能解决你的问题,请参考以下文章