• 【BZOJ3944】 Sum


    Description

    Input

    一共T+1行
    第1行为数据组数T(T<=10)
    第2~T+1行每行一个非负整数N,代表一组询问

    Output

    一共T行,每行两个用空格分隔的数ans1,ans2

    Sample Input

    6
    1
    2
    8
    13
    30
    2333

    Sample Output

    1 1
    2 0
    22 -2
    58 -3
    278 -3
    1655470 2

    Solution

    裸的杜教筛。具体的内容详见洲阁2015年的集训队论文。这里我就大致口胡一下,求一个积性函数的前缀和可以把它狄利克雷卷积上另一个函数,同时卷上的这个函数和卷完得到的这个函数如果都很好求前缀和的话,那么就可以用杜教筛来求。phi函数大致的推导如下:

     

     Code

     1 #include <cstdio>
     2 #include <map>
     3 
     4 #define R register
     5 #define maxn 2000010
     6 typedef long long ll;
     7 int phi[maxn], miu[maxn], pr[maxn / 10], prcnt;
     8 ll sph[maxn], smi[maxn];
     9 bool vis[maxn];
    10 const int moha = 3333331;
    11 struct Hash {
    12     Hash *next;
    13     int ps; ll ans;
    14 } *last1[moha], *last2[moha], mem[moha], *tot = mem;
    15 inline ll S1(R int n)
    16 {
    17     if (n < maxn) return sph[n];
    18     for (R Hash *iter = last1[n % moha]; iter; iter = iter -> next)
    19         if (iter -> ps == n) return iter -> ans;
    20 
    21     R ll ret = 1ll * n * (n + 1ll) / 2;
    22     for (R ll i = 2, j; i <= n; i = j + 1)
    23     {
    24         j = n / (n / i);
    25         ret -= S1(n / i) * (j - i + 1);
    26     }
    27     *++tot = (Hash) {last1[n % moha], n, ret}; last1[n % moha] = tot;
    28     return ret;
    29 }
    30 inline ll S2(R int n)
    31 {
    32     if (n < maxn) return smi[n];
    33     for (R Hash *iter = last2[n % moha]; iter; iter = iter -> next)
    34         if (iter -> ps == n) return iter -> ans;
    35 
    36     R ll ret = 1;
    37     for (R ll i = 2, j; i <= n; i = j + 1)
    38     {
    39         j = n / (n / i);
    40         ret -= (j - i + 1) * S2(n / i);
    41     }
    42     *++tot = (Hash) {last2[n % moha], n, ret}; last2[n % moha] = tot;
    43     return ret;
    44 }
    45 int main()
    46 {
    47     R int T; scanf("%d", &T);
    48     phi[1] = sph[1] = 1;
    49     miu[1] = smi[1] = 1;
    50     for (R int i = 2; i < maxn; ++i)
    51     {
    52         if (!vis[i]) pr[++prcnt] = i, phi[i] = i - 1, miu[i] = -1;
    53         sph[i] = sph[i - 1] + phi[i];
    54         smi[i] = smi[i - 1] + miu[i];
    55         for (R int j = 1; j <= prcnt && 1ll * i * pr[j] < maxn; ++j)
    56         {
    57             vis[i * pr[j]] = 1;
    58             if (i % pr[j])
    59             {
    60                 phi[i * pr[j]] = phi[i] * (pr[j] - 1);
    61                 miu[i * pr[j]] = -miu[i];
    62             }
    63             else
    64             {
    65                 phi[i * pr[j]] = phi[i] * pr[j];
    66                 miu[i * pr[j]] = 0;
    67                 break;
    68             }
    69         }
    70     }
    71     for (; T; --T)
    72     {
    73         R int N; scanf("%d", &N);
    74 //        printf("%d
    ", N);
    75         printf("%lld %lld
    ", S1(N), S2(N));
    76     }
    77     return 0;
    78 }
    79 /*
    80 6
    81 1
    82 2
    83 8
    84 13
    85 30
    86 2333
    87 */
  • 相关阅读:
    解析空白符(空白,制表)分隔的字串
    关于select—页面中的ListBox的Javascript
    【函数】strcat源代码
    【SQL语法】系列08:利用Update更新表中数据
    【函数】fill和fill_n填充之区别
    【Xcode】编辑与调试
    【网站】在WAMP下安装wordpress
    【SQL语法】系列06:利用ORDER BY排序
    【SQL语法】系列07:利用insert into插入新行
    【Boost】系列03:内存管理之shared_ptr智能指针
  • 原文地址:https://www.cnblogs.com/cocottt/p/7077488.html
Copyright © 2020-2023  润新知