51 Nod 1441 质因子筛

来源:互联网 发布:java引入js跨域 编辑:程序博客网 时间:2024/06/05 00:23

题目链接

题目来源: Codeforces
题意很好理解,简单归纳总结之后能发现此题本质就是求1~n每个数的质因子个数的前缀和。

因为时限6000ms,我先将1~5e6的素数 线性筛出来,然后1~5e6预处理遍历,然后求前缀和,3000ms+过掉此题

弱者的预处理:

void init(){    vis[0] = vis[1] = 1;    tot = 0;    for(int i=2 ;i<A ;i++){        if(vis[i] == 0){            cnt[i]++;            pri[++tot] = i;        }        for(int j=1 ;j<=tot&&i*pri[j]<A ;j++){            vis[i*pri[j]] = 1;            if(i % pri[j] == 0) break;        }    }    for(int i=2 ;i<A ;i++){        int now = i;        for(int j=1 ;j<=tot && pri[j]*pri[j]<=now ;j++){            if(now % pri[j] == 0){                while(now % pri[j] == 0){                    cnt[i]++;                    now /= pri[j];                }                if(now <= 1) break;                if(vis[now] == 0){cnt[i]++;break;}            }        }    }    sum[0] = sum[1] = 0;    for(int i=2 ;i<A ;i++){        sum[i] = sum[i-1] + cnt[i];    }}

然后看了tls的代码,发现原来只需要在线性筛的时候稍微改动一下就好了,道理也很好理解。我们每次是枚举了一个质数去i 筛掉 合数,比如 12=433为素数,故12的质因子数可以直接表示成4的质因子数加1

强者的预处理:(真是巧妙啊~

void init(){    vis[0] = vis[1] = 1;    sum[0] = sum[1] = 0;    tot = 0;    for(int i=2 ;i<A ;i++){        if(vis[i] == 0){            pri[++tot] = i;            vis[i] = 1;        }        for(int j=1 ;j<=tot&&i*pri[j]<A ;j++){            vis[i*pri[j]] = vis[i] + 1;            if(i % pri[j] == 0) break;        }        sum[i] = sum[i-1] + vis[i];    }}
原创粉丝点击