zoukankan      html  css  js  c++  java
  • 【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 */
  • 相关阅读:
    eclipse下c/cpp " undefined reference to " or "launch failed binary not found"问题
    blockdev 设置文件预读大小
    宝宝语录
    CentOS修改主机名(hostname)
    subprocess报No such file or directory
    用ldap方式访问AD域的的错误解释
    英特尔的VTd技术是什么?
    This virtual machine requires the VMware keyboard support driver which is not installed
    Linux内核的文件预读详细详解
    UNP总结 Chapter 26~29 线程、IP选项、原始套接字、数据链路访问
  • 原文地址:https://www.cnblogs.com/cocottt/p/7077488.html
Copyright © 2011-2022 走看看