• 杜教筛


    其实不是什么特别毒瘤的东西

    用于求F = ∑ni = 1  f(i)

    然鹅F如果难算的话

    就找到好计算的 G,H

    使得f * g = h

    那么

    ni = 1  (f * g)(i) = ∑nj = 1 g(j) * ∑n / ik = 1  f(k) 

    ni = 1   (f * g) (i) = ∑ni = 1 h(i) 

    则可合并移项得出F的表示

    比较常见的是 mu 和 phi

    mu : F(n) = 1 - ∑ni = 2 F(n / i); 

    phi : F(n) = n * (n + 1) / 2 - ∑ni = 2 F(n / i);

    模板题

    这道题用到了一个很妙的结论

    n以内两两互质的数对个数

    S(n) = ∑ni = 1 nj = 1 [gcd(i, j) == 1]

            = ∑nd = 1 μ(d)  * (n / d); 下取整

    所以n以内欧拉函数和就是 ((S(n) - 1) / 2) + 1;

    链接 : 【模板】杜教筛(Sum)

    附上代码:

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <map>
     4 using namespace std;
     5 const int N = 2e6;
     6 bool ism[N];
     7 int prm[N], ps;
     8 int mu[N];
     9 map<int, long long> sm;
    10 
    11 void sieve(){
    12     mu[1] = ism[1] = 1;
    13     for(int i = 2; i < N; i++){
    14         if(!ism[i]) mu[i] = -1, prm[++ps] = i;
    15         for(int j = 1; j <= ps && prm[j] * i < N; j++){
    16             ism[prm[j] * i] = 1;
    17             if(!(i % prm[j])) break;
    18             mu[i * prm[j]] = -mu[i];
    19         }
    20     } 
    21     for(int i = 2; i < N; i++)
    22         mu[i] += mu[i - 1];
    23 }
    24 
    25 long long sum_mu(int x){
    26     if(x < N) return mu[x];
    27     if(sm.count(x)) return sm[x];
    28     int i = 2, j; 
    29     long long ret = 1;
    30     while(i <= x){
    31         j = x / (x / i);
    32         ret -= (long long)(j - i + 1) * sum_mu(x / i);
    33         i = j + 1;
    34     }
    35     return sm[x] = ret;
    36 }
    37 
    38 long long sum_phi(int x){
    39     long long ret = 0;
    40     long long i = 1, j;
    41     while(i <= x){
    42         j = x / (x / i);
    43         ret += (x / i) * (x / i) * (sum_mu(j) - sum_mu(i - 1));
    44         i = j + 1;
    45     }
    46     return ((ret - 1) >> 1) + 1;
    47 }
    48 
    49 int main(){
    50     sieve();
    51     int T; scanf("%d", &T);
    52     int x;
    53     long long a1, a2;
    54     while(T--){
    55         scanf("%d", &x);
    56         a1 = sum_mu(x); a2 = sum_phi(x);
    57         printf("%lld %lld
    ", a2, a1);
    58     }
    59     return 0;    
    60 }
    杜教筛
  • 相关阅读:
    TApplication元件的OnIdle事件
    Query1AfterScroll 与 DataSource1DataChange 区别
    禁用表外键
    oracle al32utf8 字符长度
    Oracle表空间等操作
    delphi组件说明
    delhpi控件替换
    程序提示Google Internet Authority G2 证书不可用
    PostMessage用法
    OnKeyPress OnKeyDown区别
  • 原文地址:https://www.cnblogs.com/hjmmm/p/9416452.html
Copyright © 2020-2023  润新知