• 【搜索】【约数个数定理】[HAOI2007]反素数ant


    对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
    如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。


    所以,n以内的反质数即为不超过n的约数个数最多的数。

    怎样计算约数个数?

    约数个数定理:
    对于一个大于1正整数n可以分解质因数:n=p1^a1*p2^a2*p3^a3*…*pk^ak,
    则n的正约数的个数就是(a1+1)(a2+1)(a3+1)…(ak+1) .
    其中a1、a2、a3…ak是p1、p2、p3,…pk的指数。
     
    所以,只需枚举一个数的所有质因数就行。
     
    最多用到的 不同的 质因数 有多少呢?
     
    ∵2*3*5*7*11*13*17*19*23*29>2000000000
     
    ∴最多只用用到这么多不同的质因数。
     
    搜索即可。
     
    加两个剪枝:
    ①从小到大枚举质因数,不要让 顺序不同的 算作不同的方案。
     
    ②小的因数的指数必然大于大的因数的指数,
    ∵<1>约数个数相同时,小的数更优。
    <2>大的数与小的数有相同的因数个数时,根据定义,大的数压根不是反质数了。

    Code:
     1 #include<cstdio>
     2 #include<iostream>
     3 using namespace std;
     4 const int prime[]={0,2,3,5,7,11,13,17,19,23,29};
     5 int n,Time[11],sum;
     6 long long ans;
     7 int Calc()
     8 {
     9     int res=1;
    10     for(int i=1;i<=10;i++)
    11       res*=(Time[i]+1);
    12     return res;
    13 }
    14 void dfs(long long now,int last)
    15 {
    16     if(now>n)
    17       return;
    18     int tmp=Calc();
    19     if(sum<tmp||(sum==tmp&&now<ans)){sum=tmp;ans=now;}
    20     for(int i=1;i<=10;i++)
    21       if(Time[i]<Time[i-1]&&i>=last)
    22         {
    23             Time[i]++;
    24             dfs(now*prime[i],i);
    25             Time[i]--;
    26         }
    27 }
    28 int main()
    29 {
    30     scanf("%d",&n);
    31     Time[0]=2147483647;
    32     dfs(1,0);
    33     cout<<ans<<endl;
    34     return 0;
    35 }
    ——The Solution By AutSky_JadeK From UESTC 转载请注明出处:http://www.cnblogs.com/autsky-jadek/
  • 相关阅读:
    luogu P4284 [SHOI2014]概率充电器 期望 概率 树形dp
    luogu P5161 WD与数列 SAM 线段树合并 启发式合并
    5.5 省选模拟赛 B Permutation 构造 贪心
    luogu P3761 [TJOI2017]城市 树的直径 bfs
    一本通 1783 矩阵填数 状压dp 容斥 计数
    CF R638 div2 F Phoenix and Memory 贪心 线段树 构造 Hall定理
    BSOJ 5445 -- 【2018雅礼】树 prufer序列 dp
    CF1037H Security 线段树合并 SAM
    c++11の顺序容器
    c++11の关联容器
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/3959469.html
Copyright © 2020-2023  润新知