我一开始以为有什么很牛逼的方法来做,然后一直没有思路

后来看了https://blog.csdn.net/zju2016/article/details/78562932的博客

竟然是暴搜???????????/

好我服了

大致思路:素数的范围在100以内

因为要求尽量小,所以素数取得要尽量小

在100内的素数有20多个,这20多个配合上幂

是可以凑到2的63次方那么大的

那么我们枚举素数,得出的组合个数再与题目给的比较

然后这里有个贪心,因为要尽量小,所以素数小的要取多一些

大的取小一些,所以素数幂应该随着素数增大越来越小

然后有个比较难理解的是给一个数字怎么算组合个数

假设p = a1^k1 * a2^k2 ……ak ^ kr

其实就是算有重复元素的全排列

可以理解为有k1个a, k2个b, k3个c ……

然后求全排列

那么我们设一共有n个元素,即k1 + k2 ……kr = n

那么假设最终答案为x

那么x * k1! * k2! ……kr! = n!

也就是说如果不看重复,总的排列数为n的阶乘

那么如果看重复就是x种,而每一种里面每一块

重复的元素都可以做一个小的全排列。

例如k1个a, 就有k1 !个方案

根据乘法原理,x * k1! * k2!……kr! 所得出的也是不看重复下全排列的个数

所以移项可以得x = n! /( k1 ! * k2!……kr!)

讲这个干嘛呢?

主要是为了解释加入了新元素组合总数会有什么变化

设在原来的基础上新加入了k个相同的元素

那么 新的方案x1 = (n+k)! /( k1 ! * k2!……kr! * k!)

那么我们用x1/x,可以算出

x1 / x = (n+k)! / (n!*k!)

看到(n+k)! / (n!*k!)你想到了什么?????

非常巧的是,这就是c(n+k, k)

所以我们可以预处理组合数。

#include<cstdio>
#include<cstring>
#include<vector>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std; typedef unsigned long long ull;
const int MAXN = 112;
ull c[MAXN][MAXN], n;
bool is_prime[MAXN];
vector<int> prime; void init()
{
memset(is_prime, true, sizeof(is_prime)); //线性筛法
is_prime[0] = is_prime[1] = false;
REP(i, 2, MAXN)
{
if(is_prime[i]) prime.push_back(i);
REP(j, 0, prime.size())
{
if(i * prime[j] >= MAXN) break;
is_prime[i * prime[j]] = false;
if(i % prime[j] == 0) break;
}
} REP(i, 0, MAXN) //推组合数
{
c[i][0] = c[i][i] = 1;
REP(j, 1, i) c[i][j] = c[i-1][j-1] + c[i-1][j];
}
} void dfs(ull k, ull& ans, ull now, int ind, int pre, int up) //pre就是幂的总数,ind是当前应该从哪个素数开始用
{ //up是为了保证小的素数取得多,这样更优
if(k > ans || ind > prime.size() || now > n) return; //超级无敌剪枝
if(now == n) { ans = k; return; }
ull t = 1;
REP(i, 1, up + 1) //枚举当前这个素数的幂
{
t *= prime[ind];
if(k > ans / t) return; //这么写防止溢出
dfs(k * t, ans, now * c[pre+i][i], ind + 1, pre + i, i); //注意这里now的更新,解析中推过了
}
} int main()
{
init();
while(~scanf("%llu", &n))
{
if(n == 1) { puts("1 2"); continue; } //我觉得2不能分解成素数乘积,组合的个数应该是0
ull ans = 1ULL << 63; //但是题目样例是这么给的,那么就特判吧。
dfs(1, ans, 1, 0, 0, 63);
printf("%llu %llu\n", n, ans);
}
return 0;
}

最新文章

  1. C++学习笔记 宏 const 内联 枚举
  2. Ms sql行转列。汇总
  3. MyEclipse生成WAR包并在Tomcat下部署发布(转发)
  4. C# 文件夹加密
  5. [zhang] ViewController的生命周期分析和使用
  6. ahjesus约束方法或属性的调用方
  7. 我的NopCommerce之旅(6): 应用启动
  8. 疯狂学习java web5(SSI框架)
  9. Oracle函数function
  10. C/C++ 知识点---sizeof使用规则及陷阱分析(网摘)
  11. php 设计模式(转)
  12. supervisor管理php-fpm
  13. sys模块进度条玩法笔记
  14. bcftools或vcftools提取指定区段的vcf文件(extract specified position )
  15. [每天解决一问题系列 - 0005] WiX Burn 如何校验chained package的合法性
  16. 工具链接redis
  17. [z] Git pull 强制覆盖本地文件
  18. 自制“低奢内”CSS3注册表单,包含JS验证哦。请别嫌弃,好吗?。
  19. 快速排序,一个爱情故事-java版
  20. 关于Unity中的光照(七)

热门文章

  1. 数学之路-python计算实战(6)-numpy-ndarray
  2. vijos - P1732能量採集 (状态转移)
  3. bzoj1010: [HNOI2008]玩具装箱toy(DP+斜率优化)
  4. centos 服务器配置注意项
  5. js中字符串下划线转为驼峰
  6. 记intel杯比赛中各种bug与debug【其三】:intel chainer的安装与使用
  7. CF620E New Year Tree(线段树+二进制)
  8. Python 生成器 Generator 和迭代器 Iterator
  9. Java基础学习总结(23)——GUI编程
  10. hihoCoder #1127 : 二分图二&#183;二分图最小点覆盖和最大独立集