对于任意输入的正整数n,请编程求出具有n个不同因子的最小正整数m。

Solution

(乍一看很简单却搞了好久?我真是太菜了)

根据因子个数计算公式

若 \(m = \prod p_i^{q_i}\), 则 \(n = \prod (q_i + 1)\)

设 \(f[i][j]\) 为只包含前 \(j\) 个质因数,因子个数为 \(i\) 的最小的数

转移类似背包: \(f[i][j]=min_{k|i} (f[i/k][j-1] \cdot p_j^{k-1})\)

这样直接做是 \(O(n \sqrt n \log n)\) ,考虑到需要枚举的 \(i\) 有且仅有 \(n\) 的因数,而约数个数的一个宽上界是 \(O(\sqrt n)\),复杂度就压缩到了 \(O(n \log n)\)

使用高精度直接 dp 可能会复杂度爆炸,所以我们对数一下

#include <bits/stdc++.h>
using namespace std; struct Biguint {
int a[100005], len; Biguint() {
memset(a, 0, sizeof a);
len = 0;
} void read() {
string str;
cin >> str;
memset(a, 0, sizeof a);
len = str.length();
for (int i = 0; i < str.size(); i++)
a[i] = str[str.length() - i - 1] - '0';
} void print() {
for (int i = len - 1; i >= 0; i--) {
cout << a[i];
}
} bool operator < (const Biguint& obj) {
const int* b = obj.a;
if (this->len == obj.len) {
for (int i = len - 1; i>=0; --i)
if (a[i] != b[i]) return a[i] < b[i];
return false;
}
else return this->len < obj.len;
} bool operator > (const Biguint& obj) {
const int* b = obj.a;
if (this->len == obj.len) {
for (int i = len - 1; i>=0; --i)
if (a[i] != b[i]) return a[i] > b[i];
return false;
}
else return this->len > obj.len;
} bool operator != (const Biguint& obj) {
return (*this < obj) | (*this > obj);
} bool operator == (const Biguint& obj) {
return !((*this < obj) | (*this > obj));
} bool operator <= (const Biguint& obj) {
return (*this) < obj || (*this) == obj;
} bool operator >= (const Biguint& obj) {
return (*this) > obj || (*this) == obj;
} Biguint operator += (const Biguint& obj) {
const int* b = obj.a;
if (obj.len > len) len = obj.len;
for (int i = 0; i < len; i++) {
a[i] += b[i];
if (a[i] >= 10) a[i + 1] += a[i] / 10, a[i] %= 10;
}
if (a[len]) ++len;
while (a[len - 1] >= 10)
a[len] += a[len - 1] / 10, a[len - 1] %= 10, ++len;
return *this;
} Biguint operator + (const Biguint& obj) {
Biguint ret;
ret += *this;
ret += obj;
return ret;
} Biguint operator -= (const Biguint& obj) {
const int* b = obj.a;
for (int i = 0; i < len; i++) {
a[i] -= b[i];
if (a[i] < 0) a[i + 1]--, a[i] += 10;
}
while (a[len - 1] == 0 && len > 0) --len;
return *this;
} Biguint operator -(const Biguint& obj) {
Biguint ret;
ret += *this;
ret -= obj;
return ret;
} Biguint operator *= (int b) {
for (int i = 0; i < len; i++)
a[i] *= b;
for (int i = 0; i < len; i++)
a[i + 1] += a[i] / 10, a[i] %= 10;
++len;
while (a[len - 1] >= 10)
a[len] += a[len - 1] / 10, a[len - 1] %= 10, ++len;
while (a[len - 1] == 0 && len > 0) --len;
return *this;
} Biguint operator * (int b) {
Biguint ret;
ret = *this;
ret *= b;
return ret;
} Biguint operator * (const Biguint& obj) {
const int* b = obj.a;
Biguint ret;
for (int i = 0; i < len; i++)
for (int j = 0; j < obj.len; j++)
ret.a[i + j] += a[i] * b[j];
for (int i = 0; i < len + obj.len; i++)
ret.a[i + 1] += ret.a[i] / 10, ret.a[i] %= 10;
ret.len = len + obj.len;
++ret.len;
while (ret.a[ret.len - 1])
ret.a[ret.len] += ret.a[ret.len - 1] / 10, ret.a[ret.len - 1] %= 10, ++ret.len;
while (ret.a[ret.len - 1] == 0 && ret.len > 0) --ret.len;
return ret;
} }; ostream& operator << (ostream& os, Biguint num)
{
for (int i = num.len - 1; i >= 0; --i)
os << num.a[i];
if (num.len == 0) os << "0";
return os;
} istream& operator >> (istream& is, Biguint& num)
{
string str;
is >> str;
memset(num.a, 0, sizeof num.a);
num.len = str.length();
for (int i = 0; i < str.length(); i++)
num.a[i] = str[str.length() - i - 1] - '0';
return is;
} const int N = 500005;
const int p[21] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71};
int n,g[50005][21],h[50005][21],ii[50005],top;
double lp[21]={},f[50005][21]; signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) if(n%i==0) ii[++top]=i;
for(int i=1;i<=20;i++) lp[i]=log(p[i]);
for(int i=0;i<=50000;i++) for(int j=0;j<=20;j++) f[i][j]=1e9;
f[1][0]=1;
for(int _i=2;_i<=top;_i++) {
int i=ii[_i];
int sq=sqrt(i);
for(int j=1;j<=20;j++) {
for(int k=1;k<=sq;k++) {
if(i%k==0) {
if(f[i][j]>f[i/k][j-1]+(k-1)*lp[j]) {
f[i][j]=f[i/k][j-1]+(k-1)*lp[j];
g[i][j]=i/k;
h[i][j]=k-1;
}
}
}
for(int u=1;u<=sq;u++) {
int k=i/u;
if(i%k==0) {
if(f[i][j]>f[i/k][j-1]+(k-1)*lp[j]) {
f[i][j]=f[i/k][j-1]+(k-1)*lp[j];
g[i][j]=i/k;
h[i][j]=k-1;
}
}
}
}
}
int pos=n;
Biguint ans;
ans.len=1;
ans.a[0]=1;
for(int j=20;j;--j) {
int i=pos;
for(int k=1;k<=h[i][j];k++) ans*=p[j];
pos=g[i][j];
}
cout<<ans;
}

[HNOI2001] 求正整数 - 背包dp,数论的更多相关文章

  1. BZOJ 1225: [HNOI2001] 求正整数( dfs + 高精度 )

    15 < log250000 < 16, 所以不会选超过16个质数, 然后暴力去跑dfs, 高精度计算最后答案.. ------------------------------------ ...

  2. 高精度+搜索+质数 BZOJ1225 [HNOI2001] 求正整数

    // 高精度+搜索+质数 BZOJ1225 [HNOI2001] 求正整数 // 思路: // http://blog.csdn.net/huzecong/article/details/847868 ...

  3. bzoj1225 [HNOI2001] 求正整数

    1225: [HNOI2001] 求正整数 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 762  Solved: 313[Submit][Statu ...

  4. luogu P1128 [HNOI2001]求正整数 dp 高精度

    LINK:求正整数 比较难的高精度. 容易想到贪心不过这个贪心的策略大多都能找到反例. 考虑dp. f[i][j]表示前i个质数此时n的值为j的最小的答案. 利用高精度dp不太现实.就算上FFT也会T ...

  5. 【BZOJ】1225: [HNOI2001] 求正整数

    http://www.lydsy.com/JudgeOnline/problem.php?id=1225 题意:给一个数n,求一个最小的有n个约数的正整数.(n<=50000) #include ...

  6. [HNOI2001]求正整数

    题目描述 对于任意输入的正整数n,请编程求出具有n个不同因子的最小正整数m. 例如:n=4,则m=6,因为6有4个不同整数因子1,2,3,6:而且是最小的有4个因子的整数. 输入输出格式 输入格式: ...

  7. BZOJ 1225: [HNOI2001] 求正整数 高精度+搜索+质数

    题意:给定n求,有n个因子的最小正整数. 题解:水题,zcr都会,我就不说什么了. 因数个数球求法应该知道,将m分解质因数,然后发现 a1^p1*a2^p2....an^pn这样一个式子, (1+p1 ...

  8. P1128 [HNOI2001]求正整数

    传送门 rqy是我们的红太阳没有它我们就会死 可以考虑dp,设\(dp[i][j]\)表示只包含前\(j\)个质数的数中,因子个数为\(i\)的数的最小值是多少,那么有转移方程 \[f[i][j]=m ...

  9. BZOJ1222: [HNOI2001]产品加工(诡异背包dp)

    Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 907  Solved: 587[Submit][Status][Discuss] Descriptio ...

随机推荐

  1. centos6.8 安装.net core2.1 sdk 或 .net core2.1 runtime

    前段时间看.net core 更更更新了,大家反应都挺好,想有机会也学习一下,正好这两天要写一个简单的服务在centos上面跑,于是决定放弃使用java,直接.net core走起来,事情进行的非常顺 ...

  2. 二进制、十六进制理解及int类型二进制存储方式

    二进制 0000 0000 0000 0000 0000 0000 0000 0001 // 2^0 0000 0000 0000 0000 0000 0000 0000 0010 // 2^1 00 ...

  3. Python爬虫实战教程:爬取网易新闻;爬虫精选 高手技巧

    前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. stars声明很多小伙伴学习Python过程中会遇到各种烦恼问题解决不了.为 ...

  4. html网页基本概念

    什么是网页?html文档经过浏览器内核渲染后展示出来的页面(五大主流浏览器及四大内核) html文档文件名后缀是.html,之前存在的.htm是为支持DOM系统(目前织梦还是用.htm文件名结尾文件) ...

  5. JS DOM用不同方法获取节点及对节点插入、复制和移除

    操作节点的方法 appendChild() insertBefore() replaceChild() cloneNode() normalize() splitText() sppendChild( ...

  6. MySQL概述及入门(四)

    MySql概述及入门(四) 什么是MySQL的锁? 数据库锁定机制,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则,简单说,就是不让别人动 总的来说,MySQL各 ...

  7. java读取中文文本文件乱码问题

    今天遇到的问题是这样:用java读取一个中文文本文件,但读取到的却是乱码,之前一直没有问题,查清楚后,原来是因为今天是用的windows的记事本来编辑的文件,因编码方式是的不同而导致了乱码,解决方法就 ...

  8. 『后缀自动机入门 SuffixAutomaton』

    本文的图片材料多数来自\(\mathrm{hihocoder}\)中详尽的\(SAM\)介绍,文字总结为原创内容. 确定性有限状态自动机 DFA 首先我们要定义确定性有限状态自动机\(\mathrm{ ...

  9. generalization error

    泛化误差 机器学习中的Bias(偏差),Error(误差),和Variance(方差)有什么区别和联系? 准与确的关系 bias 偏差:模型越复杂,模型的偏差越小,方差越小,因此会出现overfitt ...

  10. 吴裕雄--天生自然HADOOP操作实验学习笔记:tf-idf算法

    实验目的 通过实验了解tf-idf算法原理 通过实验了解mapreduce的更多组件 学会自定义分区,读写缓存文件 了解mapreduce程序的设计方法 实验原理 1.TF-IDF简介 TF-IDF( ...