首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Codeforces 547C Mike and Foam:質因子分解 + 容斥原理動態維護互質對數

     編輯:關於C++

問題描述

有 n (≤ 2×10⁵) 種啤酒,第 i 種濃度 aᵢ (≤ 5×10⁵)。初始集合為空。q (≤ 2×10⁵) 次操作:
x:若 aₓ 不在集合中則加入,否則移除。
每次操作後輸出:集合中互質數對個數(即 gcd(aᵢ, aⱼ) = 1 的無序對數)。

核心思路:容斥原理 + 動態計數

設當前集合大小為 S。新增元素 v 時,互質對增加量 = S - (與 v 不互質的元素數)。
移除元素 v 時,互質對減少量 = (S-1) - (與 v 不互質的其他元素數)。

關鍵子問題:快速查詢「集合中有多少數與 v 不互質」。

質因子分解 + 容斥

v ≤ 5×10⁵,質因子個數 ≤ 6(因 2×3×5×7×11×13×17 > 5×10⁵)。
設 v 的不同質因子為 p₁..pₖ。
與 v 不互質 ⇔ 能被至少一個 pᵢ 整除。
用容斥原理:對所有非空子集,計算集合中能被該子集乘積整除的數,奇加偶減。

動態維護:計數器數組

維護 cnt[d] = 當前集合中能被 d 整除的元素個數(d 為無平方因子數,即質因子乘積)。
新增 v:枚舉其質因子子集,乘積 d,cnt[d]++。
移除 v:同理 cnt[d]--。
查詢不互質數:枚舉子集,奇加偶減 cnt[d]。

特殊情況:v = 1

1 與任何數互質。單獨維護 one = 集合中 1 的個數。
新增 1:互質對增加 S(與所有現有元素互質)。
移除 1:互質對減少 S-1。

代碼核心


vector primes[500001]; // 預處理每數的質因子
int cnt[500001] = {0};
ll ans = 0;
int one = 0;
unordered_set S; // 或 bool inSet[]

void add(int v) {
    if (v == 1) { ans += S.size(); one++; S.insert(1); return; }
    int notCoprime = 0;
    vector& pf = primes[v];
    int k = pf.size();
    for (int mask = 1; mask < (1<

複雜度

  • 預處理質因子:O(N log log N) 篩法
  • 每次操作:O(2ᵏ) ≤ 64,極快
  • 總計:O((n+q) log log MAX + q·2ᵏ) ≈ 10⁷ 操作

總結

CF 547C 是質因子分解 + 容斥原理 + 動態計數器的完美結合。關鍵點:
1. 數值 ≤ 5×10⁵ ⇒ 質因子 ≤ 6 ⇒ 子集枚舉極快
2. 維護 cnt[d] 實現 O(1) 查詢「能被 d 整除的個數」
3. 互質對增量 = 集合大小 - 不互質數
4. 1 的特殊處理
此模板廣泛適用於「動態集合互質查詢、倍數查詢」類問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved