HDU 4135 容斥
问a,b区间内与n互质个数,a,b<=1e15,n<=1e9
n才1e9考虑分解对因子的组合进行容斥,因为19个最小的不同素数乘积即已大于LL了,枚举状态复杂度不会很高。然后差分就好了。
/** @Date : 2017-09-28 16:52:30 * @FileName: HDU 4135 容斥.cpp * @Platform: Windows * @Author : Lweleth (SoungEarlf@gmail.com) * @Link : https://github.com/ * @Version : $Id$ */ #include <bits/stdc++.h> #define LL long long #define PII pair<int ,int> #define MP(x, y) make_pair((x),(y)) #define fi first #define se second #define PB(x) push_back((x)) #define MMG(x) memset((x), -1,sizeof(x)) #define MMF(x) memset((x),0,sizeof(x)) #define MMI(x) memset((x), INF, sizeof(x)) using namespace std; const int INF = 0x3f3f3f3f; const int N = 1e5+20; const double eps = 1e-8; LL pri[N]; bool vis[N]; int c; void prime() { MMF(vis); for(int i = 2; i < N; i++) { if(!vis[i]) pri[c++] = i; for(int j = 2; j < c && i * pri[j] < N; j++) { vis[i * pri[j]] = 1; if(i % pri[j] == 0) break; } } //19个最小的不同素数乘积即已大于2^63 - 1 /*LL t = 1; for(int i = 0; i < 100; i++) t *= pri[i], cout << t <<"~" <<i<<endl;*/ } int main() { prime(); int T; cin >> T; int icas = 0; while(T--) { LL n, a, b; scanf("%lld%lld%lld", &a, &b, &n); int cnt = 0; vector<LL>q; for(int i = 0; i < c && pri[i] <= n / pri[i]; i++) { if(n % pri[i] == 0) { while(n % pri[i] == 0) n /= pri[i]; q.PB(pri[i]); cnt++; } } if(n > 1) q.PB(n), cnt++; LL ansa = 0; LL ansb = 0; for(int i = 1; i < (1 << cnt); i++) { LL t = 1; int f = -1; for(int j = 0; j < cnt; j++) if((i & (1 << j))) t *= q[j], f *= -1; //cout << t << endl; ansb += f * (b / t); ansa += f * ((a - 1) / t); } //cout << ansa <<"~" <<ansb<<endl; LL ans = b - ansb - (a - 1 - ansa); printf("Case #%d: %lld\n", ++icas, ans); } return 0; }