zoukankan      html  css  js  c++  java
  • [HAOI2007]反素数

    嘟嘟嘟

     

    做这道题得自己推出这么几个结论……

     

    1.最大的反素数一定是约数个数最多的的数中最小的那个。

      这个其实很好想:根据定义,$g(x)$要大于任意的$g(i)$,而不是大于等于。

    2.1~n中任意一个数的不同的质因子不会超过10个,且所有质因子的指数之和不会大于30.

      最小的10个质数的乘积刚好大于$2^{31}$了,而$2^{31} > 2 * 10^9$。

    3.把$x$分解质因数:$x = 2^{a_1} * 3^{a_2} * 5^{a_3} * 7^{a_4} * …… * 29^{a_{10}}$,一定满足$a_1 leqslant a_2 leqslant a_3 leqslant …… leqslant a_{10}$.

      证明用反证法。假设$x$中有一项$p_k(p > 29)$,那么根据第二条结论,前10个质数中一定有一个$p'$不能整除$x$,那么我们应该用$p'$代替$p$,因为这即保证了约数相等,新的数又更小。

      而之所以递减,是因为如果$x$有相邻的两项$p_i ^ {a_i}, p_j ^ {a_j}(p_i < p_j, a_i > a_j)$,那么完全可以构造出另一个数$x'$,其中两项为$p_i ^ {a_j}, p_j ^{a_i}$,根据算数基本定理,$x$和$x'$约数个数相等,但是$x'$更小,所以应该选$x'$。

    知道这几条结论后,一波爆搜就行了。

     (爆搜我写的特别丑,是在不行了再看我的吧)

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<stack>
     9 #include<queue>
    10 #include<vector>
    11 using namespace std;
    12 #define enter puts("")
    13 #define space putchar(' ')
    14 #define Mem(a, x) memset(a, x, sizeof(a))
    15 #define rg register
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const db eps = 1e-8;
    20 //const int maxn = ;
    21 inline ll read()
    22 {
    23   ll ans = 0;
    24   char ch = getchar(), las = ' ';
    25   while(!isdigit(ch)) las = ch, ch = getchar();
    26   while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar();
    27   if(las == '-') ans = -ans;
    28   return ans;
    29 }
    30 inline void write(ll x)
    31 {
    32   if(x < 0) putchar('-'), x = -x;
    33   if(x >= 10) write(x / 10);
    34   putchar(x % 10 + '0');
    35 }
    36 
    37 ll n;
    38 const int a[] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; //num = 10
    39 ll ans1 = 0, ans = (ll)INF * (ll)INF;
    40 
    41 void dfs(ll now, int id, int sum, int Max, int tot, ll x)
    42 {
    43   if(!tot || now > n || id > 11) return;
    44   if(x > ans1 ||(x == ans1 && now < ans)) ans1 = x, ans = now;
    45   ll tp = 1;
    46   for(int i = 1; i <= min(tot, Max); ++i)
    47     {
    48       tp *= a[id];
    49       if(tp > n) break;
    50       dfs(now * tp, id + 1, sum + i, i, tot - i, x * (i + 1));
    51     }
    52 }
    53 
    54 int main()
    55 {
    56   n = read();
    57   dfs(1, 1, 0, INF, 30, 1);
    58   write(ans);  
    59   return 0;
    60 }
    View Code
  • 相关阅读:
    零基础入门:实时音视频技术基础知识全面盘点
    IM开发干货分享:如何优雅的实现大量离线消息的可靠投递
    flask_apscheduler 定时任务框架
    小程序使用 editor 富文本编辑器填坑指南
    万年深坑:mpVue 中的坑
    js利用canvas绘制爱心
    【字节跳动21届提前批】面试手撕代码——电梯调度算法
    Maximum call stack size exceeded 报错
    未安装less-loder
    05 vue前端工程化
  • 原文地址:https://www.cnblogs.com/mrclr/p/9756947.html
Copyright © 2011-2022 走看看