您的位置:首页 > 其它

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

2012-09-23 11:33 661 查看
  求比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不多但都是大数据。。。

  

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <map>
#include <queue>
#include<string>
#include<iostream>
#define MAXN 200
using namespace std;
typedef long long LL;
const int BMOD = 100000000;
const int maxl = (MAXN>>3)+1;
struct bign{
int s[maxl], len;
void init(){memset(s, 0, sizeof s); len = 1;}
void clean(){while(len > 1 && !s[len-1]) --len;}
bign(){init();}
bign(int num){*this = num;}
bign(const char *num){*this = num;}
bign operator = (int num) {
char s[maxl];
sprintf(s, "%d", num);
return *this = s;
}
bign operator = (const char *buf) {
init();
int l = strlen(buf);
for(int i = 0, j = l - 1; i < l; ++ i, -- j)
s[j >> 3] = s[j >> 3] * 10 + buf[i] - '0';
len = (l >> 3) + 1;
clean();
return *this;
}
bign operator + (const bign b) {
bign c; c.len = 0;
int g = 0;
for (int i = 0; g || i < max(len, b.len); i++) {
c.s[c.len] = g;
if(i < len)c.s[c.len] += s[i];
if(i < b.len)c.s[c.len] +=b.s[i];
g = c.s[c.len]/BMOD, c.s[c.len] %= BMOD, c.len++;
}
return c;
}
bign operator * (const bign b) {
bign c;
c.len = len + b.len;
LL lin;
for (int i = 0; i < len; i++)
for (int j = 0; j < b.len; j++){
lin = (LL)s[i] * b.s[j] + c.s[i+j];
c.s[i+j] = lin % BMOD;
c.s[i+j+1] += lin / BMOD;
}
for (int i = 0; i < c.len - 1; i++) c.s[i+1] += c.s[i] / BMOD, c.s[i] %= BMOD;
c.clean();
return c;
}
bool operator <(const bign b) const{
if(len != b.len) return len < b.len;
for (int i = len - 1; i >= 0; i--)
if (s[i] != b.s[i]) return s[i] < b.s[i];
return false;
}
bool operator <=(const bign b) const {return !(b < *this);}

void print() {
for(int i = len - 1; i >= 0; i--) {
if (i == len - 1) printf("%d", s[i]);
else printf("%08d", s[i]);
}
}
};

struct stt{
bign k;
LL f;
int n,a[MAXN];
stt(){}
stt(bign kk, LL ff, int nn) {k = kk, f= ff, n = nn;}
};

struct ans{
bign in, res;
LL f;
};
map<LL, bign> mp;
vector<ans> vec;
bign maxp, pri[MAXN];
int prs;
//pri[i]和stt里的a[i]是对应的,a[i]是pri[i]的个数
void init() {
prs = 0;
for (int i = 2, j, flag; i < MAXN; i++) {
for (flag = 1,j = 2; j < i; j++)
if (i % j == 0) flag = 0;
if (flag) pri[prs++] = i;
}
}
bool canadd(stt st) {
if (maxp < st.k) return false;
if (mp.find(st.f) == mp.end() || st.k < mp[st.f]){
mp[st.f] = st.k;
return true;
}
return false;
}
void updateans(stt st) {
for (int i = 0; i < vec.size(); i++) {
if (st.k <= vec[i].in && (st.f > vec[i].f || st.f == vec[i].f && st.k < vec[i].res))
vec[i].res = st.k, vec[i].f = st.f;
}
}
void bfs(){
queue<stt> q;
mp.clear();
mp[1] = 1;
q.push(stt(1, 1, 0));
while (!q.empty()) {
stt ost = q.front(); q.pop();
updateans(ost);
//添加已有质数
for (int i = 0 ; i < ost.n; i++) {
stt nst = ost;
nst.k = ost.k * pri[i];
nst.f = ost.f / (ost.a[i]+1) * (ost.a[i]+2);
nst.a[i]++;
if (canadd(nst)) q.push(nst);
}
//添加还未添加的质数
stt nst = ost;
nst.k = ost.k * pri[ost.n];
nst.f = ost.f * 2;
nst.a[nst.n++] = 1;
if (canadd(nst)) q.push(nst);
}
}
char s[MAXN];
int main() {
//freopen("test.in","r",stdin);
init();
maxp = 0;
vec.clear();
mp.clear();
while (scanf("%s", s) != EOF) {
ans a; a.in = s, a.res = 1, a.f = 1;
if (maxp < a.in) maxp = a.in;
vec.push_back(a);
}
bfs();
for (int i = 0; i < vec.size(); i++)
vec[i].res.print(), printf(" %I64d\n",vec[i].f);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: