码迷,mamicode.com
首页 > 其他好文 > 详细

题解 P1463 【[POI2002][HAOI2007]反素数】

时间:2019-09-12 21:40:57      阅读:105      评论:0      收藏:0      [点我收藏+]

标签:数组   计算   short   pac   赋值   class   freopen   scan   ++   

题目链接

Solution [POI2002][HAOI2007]反素数

题目大意:设\(x\)的约数个数为\(g(x)\),若对于所有\(i \in [1,x)\),都有\(g(i) < g(x)\),则称\(x\)为反素数,求不超过\(n\)的最大反素数

分析:这道题可以打表,但是打表也要讲求方法

对于\(n = 2 \times 10^9\)这种级别的数据,如果你用\(O(n^2)\)算法,估计你得搬出太湖之光才能以可以接受的速度跑完(而且你还得考虑并行计算效率问题)

我们把这个问题分成两部分解决:

  • 预处理出\(g\)
  • 计算反素数

对于第一个问题,我们可以利用筛法的思想,对于每个数,我们枚举它的倍数,然后累加,复杂度略超埃氏筛

准确来讲是\(\sum_1^n\frac{n}{i}\),然后这玩意儿接近\(nlogn\)(具体怎么证明蒟蒻真不会,从某篇博客上看到的)

对于计算反素数我们保存一个到当前位置的最大值就可以了

我们可以用\(unsigned\;short\)来保存\(g\),这样常数会小一些(缓存优化)

亲测比用\(int\)的要快\(80s\)左右

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned short type;
const int maxn = 2e9 + 100;
type *num;
int main(){
    freopen("fafa.out","w",stdout);
    num = new type[maxn];//这里最好动态分配内存,貌似Windows平台 or 比较老旧的编译器无法编译大数组?我之前CE过
    memset(num,0,sizeof(type) * maxn);//既然动态分配了那就要清0
    for(int i = 1;i <= maxn;i++){
        for(int j = 1;j * i <= maxn;j++)
            num[j * i]++;
    }
    type mx = 0;//unsigned不能赋值为-INF
    for(int i = 1;i <= maxn;i++){
        if(mx < num[i])printf("%d,",i);
        mx = max(mx,num[i]);
    }
    printf("\n");
    fflush(stdout);
    fclose(stdout);
    return 0;   
}

然后我本机跑了\(320s\)左右就打出来了一个表

然后程序就很明了(话说这题打表不会棕吧?)

#include <algorithm>
#include <cstdio>
using namespace std;
int n,i,arr[] = {1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,7560,10080,15120,20160,25200,27720,45360,50400,55440,83160,110880,166320,221760,277200,332640,498960,554400,665280,720720,1081080,1441440,2162160,2882880,3603600,4324320,6486480,7207200,8648640,10810800,14414400,17297280,21621600,32432400,36756720,43243200,61261200,73513440,110270160,122522400,147026880,183783600,245044800,294053760,367567200,551350800,698377680,735134400,1102701600,1396755360,0x7fffffff};//放置一个无穷大的哨兵,不然会RE第二个点
int main(){
    scanf("%d",&n);
    while(arr[i + 1] <= n)i++;
    return printf("%d\n",arr[i]),0;
}

话说小数据二分查找没用诶,我用了二分反而跑的更慢了,不知道那些\(0\;ms\)的神仙怎么跑出来的(上一代评测姬的锅?)

题解 P1463 【[POI2002][HAOI2007]反素数】

标签:数组   计算   short   pac   赋值   class   freopen   scan   ++   

原文地址:https://www.cnblogs.com/colazcy/p/11515099.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!