• 【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 */
  • 相关阅读:
    mysql主从部署
    解决mysql登录警告问题
    使用selenium控制已打开的浏览器
    jTopo生成网络拓扑图
    Python模拟登陆正方教务系统并抓取成绩单
    Pandas库学习笔记
    三种方法实现统计一个句子中的字母数 (setdefault、defaultdict的使用)
    numpy学习笔记
    字符串的模式匹配——Brute-Force算法和KMP算法
    用生成器来改写直接返回列表的函数
  • 原文地址:https://www.cnblogs.com/cocottt/p/7077488.html
Copyright © 2020-2023  润新知