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

题目链接

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\)的神仙怎么跑出来的(上一代评测姬的锅?)

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

时间: 2024-09-30 05:35:19

题解 P1463 【[POI2002][HAOI2007]反素数】的相关文章

P1463 [POI2002][HAOI2007]反素数

打表出奇迹!!! 这道题暴力当然能做,但是\(n==2 \times 10 ^9\)就不允许暴力了. 让我们打表出奇迹!!! 首先先了解一下如何有效率地算出一个数的约数个数: 最暴力的是从\(1\)枚举到\(n\),每一次++. 优化一点的就是只枚举到\(\sqrt{n}\).但是还是很慢的. 我们了解一下传说的约数个数定理: 对于一个正整数\(n\),由唯一分解定理可以分解为\(p_1^{a_1} \times p_2^{a_2} \times ... \times p_i^{a_i}\).

[POI2002][HAOI2007]反素数

题目描述 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4.如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数.例如,整数1,2,4,6等都是反质数.现在给定一个数N,你能求出不超过N的最大的反质数么? 此题以前学习过,此次刷POI又一次碰到了,我们看到要找到不超过N的最大反质数,我们就可以将问题转化. 在一开始的时候我将问题转化错了,我将问题转化为找到不大于N的中约数最多的数中的的最大的那个.我们考虑它为什么它不对. 令  ∀ x<y&

[POI2002][HAOI2007]反素数 数论 搜索 好题

Code: #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; int prime[]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,51,53}; ll n, maxn; int cur; void dfs(int dep,ll m,int t,int p){ //上一个指数 if(dep==12){ if(t>=cur){

[POI2002][HAOI2007]反素数(Antiprime)

题目链接 这道题需要用到整数唯一分解定理以及约数个数的计算公式.这里我就不再阐述了. 公式可以看出,只有指数影响约数个数,那么在唯一分解出的乘式中,指数放置的任何位置都是等价的.(即 23*34*57与27*34*53的约数个数相同)但很明显指数放置位置的不同会影响乘积的大小.由于所有比n小的数的约数个数都比他的约数个数小,换而言之就是约数个数不相等.即 相同约数个数,该数越小越好.那么我们运用贪心思想.尽量大的指数放置于尽量小的底数上. 题目的数据范围小于231,所以指数最大31,由之前的推论

[HAOI2007]反素数ant

1053: [HAOI2007]反素数ant Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1907  Solved: 1069[Submit][Status][Discuss] Description 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4.如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数.例如,整数1,2,4,6等都是反质数.现在给定一个数N,你能求出不超过N的最大的反质数么?

HAOI2007反素数

1053: [HAOI2007]反素数ant Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1346  Solved: 732[Submit][Status] Description 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4. 如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数.例如,整数1,2,4,6等都是反质数. 现在给定一个数N,你能求出不超过N的最大的反质数么? Input 一个

【BZOJ 1053】 1053: [HAOI2007]反素数ant (反素数)

1053: [HAOI2007]反素数ant Description 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4.如果某个正整数x满足:g(x)>g(i) 0<i<x ,则称x为反质数.例如,整数1,2,4,6等都是反质数.现在给定一个数N,你能求出不超过N的最大的反质数么 ? Input 一个数N(1<=N<=2,000,000,000). Output 不超过N的最大的反质数. Sample Input 1000 Sample Output

【BZOJ】1053: [HAOI2007]反素数ant

1053: [HAOI2007]反素数ant Description: g(x)表示x的约数个数,反素数:对于任意的i (i < x),均有g(i) < g(x),则x为反素数:现在输入不超过2e9的数,要你找出不超过N的最大的反素数: 坑点:里面的反素数是严格小于,所以对于相同的约数要取较小的. 思路:直接深搜外加剪枝即可: #include<iostream> #include<cstdio> #include<cstring> #include<

bzoj 1053: [HAOI2007]反素数ant 搜索

1053: [HAOI2007]反素数ant Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1497  Solved: 821[Submit][Status] Description 对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4.如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数.例如,整数1,2,4,6等都是反质数.现在给定一个数N,你能求出不超过N的最大的反质数么? Input 一个数N