• HDU 4392 Maximum Number Of Divisors [数学+搜索]


      求比N小的因数最多的数,因数相同时取较小的的。(N<=10^80)

      没想法的题目,没想到是搜索。。

      首先因子数目 f[i] = ∏(p[i]+1) ,p[i]是所有质因数的个数,这个应该都知道。如果要使因子最多并且数最小,不会用到太大的质数,这个我也不知道怎么证明。。原题解也没有证明。。。

      用一个四元组[K,F,N,A[]]表示数K有F个因数,包含N个质因数,每个质因数P[i]分别有A[i]个。然后搜索就可以了,添加一个已有质数A[i],四元组转化为[K*P[i],F/(A[i]+1)*(A[i]+2),N,A[i]+1],添加一个新的质数A[i],四元组转化为,[K*P[i],F*2,N+1,A[i]=1]。

      用map存所有的F对应的K,F相同时保留较小的K。

      直接做会超时,因为搜索中数是一直递增的,把结果存下来然后离线边搜边更新结果就A了,估计是因为case不多但都是大数据。。。

      

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <math.h>
      4 #include <algorithm>
      5 #include <map>
      6 #include <queue>
      7 #include<string>
      8 #include<iostream>
      9 #define MAXN 200
     10 using namespace std;
     11 typedef long long LL;
     12 const int BMOD = 100000000;
     13 const int maxl = (MAXN>>3)+1;
     14 struct bign{
     15     int s[maxl], len;
     16     void init(){memset(s, 0, sizeof s); len = 1;}
     17     void clean(){while(len > 1 && !s[len-1]) --len;}
     18     bign(){init();}
     19     bign(int num){*this = num;}
     20     bign(const char *num){*this = num;}
     21     bign operator = (int num) {
     22         char s[maxl];
     23         sprintf(s, "%d", num);
     24         return *this = s;
     25     }
     26     bign operator = (const char *buf) {
     27         init();
     28         int l = strlen(buf);
     29         for(int i = 0, j = l - 1; i < l; ++ i, -- j)
     30             s[j >> 3] = s[j >> 3] * 10 + buf[i] - '0';
     31         len = (l >> 3) + 1;
     32         clean();
     33         return *this;
     34     }
     35     bign operator + (const bign b) {
     36         bign c; c.len = 0;
     37         int g = 0;
     38         for (int i = 0; g || i < max(len, b.len); i++) {
     39             c.s[c.len] = g;
     40             if(i < len)c.s[c.len] += s[i];
     41             if(i < b.len)c.s[c.len] +=b.s[i];
     42             g = c.s[c.len]/BMOD, c.s[c.len] %= BMOD, c.len++;
     43         }
     44         return c;
     45     }
     46     bign operator * (const bign b) {
     47         bign c;
     48         c.len = len + b.len;
     49         LL lin;
     50         for (int i = 0; i < len; i++)
     51             for (int j = 0; j < b.len; j++){
     52                 lin = (LL)s[i] * b.s[j] + c.s[i+j];
     53                 c.s[i+j] = lin % BMOD;
     54                 c.s[i+j+1] += lin / BMOD;
     55             }
     56         for (int i = 0; i < c.len - 1; i++) c.s[i+1] += c.s[i] / BMOD, c.s[i] %= BMOD;
     57         c.clean();
     58         return c;
     59     }
     60     bool operator <(const bign b) const{
     61         if(len != b.len) return len < b.len;
     62         for (int i = len - 1; i >= 0; i--)
     63             if (s[i] != b.s[i]) return s[i] < b.s[i];
     64         return false;
     65     }
     66     bool operator <=(const bign b) const {return !(b < *this);}
     67 
     68     void print() {
     69         for(int i = len - 1; i >= 0; i--) {
     70             if (i == len - 1) printf("%d", s[i]);
     71             else printf("%08d", s[i]);
     72         }
     73     }
     74 };
     75 
     76 struct stt{
     77      bign k;
     78     LL f;
     79     int n,a[MAXN];
     80     stt(){}
     81     stt(bign kk, LL ff, int nn) {k = kk, f= ff, n = nn;}
     82 };
     83 
     84 struct ans{
     85     bign in, res;
     86     LL f;
     87 };
     88 map<LL, bign> mp;
     89 vector<ans> vec;
     90 bign maxp, pri[MAXN];
     91 int prs;
     92 //pri[i]和stt里的a[i]是对应的,a[i]是pri[i]的个数
     93 void init() {
     94     prs = 0;
     95     for (int i = 2, j, flag; i < MAXN; i++) {
     96         for (flag = 1,j = 2; j < i; j++)
     97             if (i % j == 0) flag = 0;
     98         if (flag) pri[prs++] = i;
     99     }
    100 }
    101 bool canadd(stt st) {
    102     if (maxp < st.k) return false;
    103     if (mp.find(st.f) == mp.end() || st.k < mp[st.f]){
    104         mp[st.f] = st.k;
    105         return true;
    106     }
    107     return false;
    108 }
    109 void updateans(stt st) {
    110     for (int i = 0; i < vec.size(); i++) {
    111         if (st.k <= vec[i].in && (st.f > vec[i].f || st.f == vec[i].f && st.k < vec[i].res))
    112             vec[i].res = st.k, vec[i].f = st.f;
    113     }
    114 }
    115 void bfs(){
    116     queue<stt> q;
    117     mp.clear();
    118     mp[1] = 1;
    119     q.push(stt(1, 1, 0));
    120     while (!q.empty()) {
    121         stt ost = q.front(); q.pop();
    122         updateans(ost);
    123         //添加已有质数
    124         for (int i = 0 ; i < ost.n; i++) {
    125             stt nst = ost;
    126             nst.k = ost.k * pri[i];
    127             nst.f = ost.f / (ost.a[i]+1) * (ost.a[i]+2);
    128             nst.a[i]++;
    129             if (canadd(nst)) q.push(nst);
    130         }
    131         //添加还未添加的质数
    132         stt nst = ost;
    133         nst.k = ost.k * pri[ost.n];
    134         nst.f = ost.f * 2;
    135         nst.a[nst.n++] = 1;
    136         if (canadd(nst)) q.push(nst);
    137     }
    138 }
    139 char s[MAXN];
    140 int main() {
    141     //freopen("test.in","r",stdin);
    142     init();
    143     maxp = 0;
    144     vec.clear();
    145     mp.clear();
    146     while (scanf("%s", s) != EOF) {
    147         ans a; a.in = s, a.res = 1, a.f = 1;
    148         if (maxp < a.in) maxp = a.in;
    149         vec.push_back(a);
    150     }
    151     bfs();
    152     for (int i = 0; i < vec.size(); i++)
    153         vec[i].res.print(), printf(" %I64d\n",vec[i].f);
    154     return 0;
    155 }
  • 相关阅读:
    Qt Creator 安装SDK,在MSVC编译模式下使用CDB调试器
    QString与std::string的相互转换
    白话代码中的复杂度分析-大O复杂度表示法 时间,空间复杂度分析 最好,最坏,平均复杂度
    QT 如何使窗体初始最大化
    make_ext4fs
    Qt5.4中遇到找不到头文件<QApplication>等
    MariaDB 数据库的备份
    MariaDB -- 数据类型
    MariaDB基础操作
    keepalived + lvs 网站高可用集群
  • 原文地址:https://www.cnblogs.com/swm8023/p/2698802.html
Copyright © 2020-2023  润新知