求區間
之間與
互質的數的個數 ,
html
將
分解質因數, 得出
個不一樣的質因數, 存到
數組中.
利用 容斥 計算
中與
不互質的數的數量
, 互質的數量則爲
.
使用
的答案再 容斥 一下就能夠了 .web
數組
部分:app
void DFS(int k, bool opt, int p_sum, const int &x){ if(k == cnt+1){ if(p_sum == 1) return ; if(!opt) Tmp_1 -= x/p_sum; else Tmp_1 += x/p_sum; return ; } DFS(k+1, opt^1, Lcm(p_sum, p[k]), x); DFS(k+1, opt, p_sum, x); }
按以上解法, 將
換成
就
了, 好奇怪.svg
癥結 ↑ spa
二進制枚舉狀態部分:code
for(reg int i = 1; i < 1<<cnt; i ++){ int p_sum = 1; int p_cnt = 0; for(reg int j = 1; j <= cnt; j ++) if((1<<j-1) & i) p_cnt ++, p_sum = Lcm(p_sum, p[j]); if(p_cnt & 1) Tmp_1 += x/p_sum; else Tmp_1 -= x/p_sum; } return x-Tmp_1;
沒什麼好說的.orm
#include<cstdio> #include<cctype> #define reg register typedef long long ll; const int maxn = 105; int Test_Cnt; int N; int cnt; int p[maxn]; ll Tmp_1; ll L; ll R; int Gcd(int a, int b){ return !b?a:Gcd(b, a%b); } int Lcm(int a, int b){ return a/Gcd(a, b)*b; } ll Calc(ll x){ if(!x) return 0; Tmp_1 = 0; for(reg int i = 1; i < 1<<cnt; i ++){ int p_sum = 1; int p_cnt = 0; for(reg int j = 1; j <= cnt; j ++) if((1<<j-1) & i) p_cnt ++, p_sum = Lcm(p_sum, p[j]); if(p_cnt & 1) Tmp_1 += x/p_sum; else Tmp_1 -= x/p_sum; } return x-Tmp_1; } void Work(){ scanf("%lld%lld%d", &L, &R, &N); cnt = 0; for(reg int d = 2; d*d <= N; d ++) if(N % d == 0){ p[++ cnt] = d; while(N%d == 0) N /= d; } if(N > 1) p[++ cnt] = N; //Attention printf("Case #%d: %lld\n", ++ Test_Cnt, Calc(R) - Calc(L-1)); } int main(){ int T; scanf("%d", &T); while(T --) Work(); return 0; }