2019.7.8 校内测试题 能量球
题目
能量球(enb.cpp,1s,128MB)
【问题描述】:
sideman 有着一个你们所不知道的秘密。实际上,sideman 不是地球人,而 是遥远的 Gliese 行星的生物。sideman 虽然身在地球,但是时刻盼望着能够回 到 Gliese 去。
终于有一天,sideman 得到了几颗蕴含着无数能量的能量球。经过漫长艰苦 的研究,sideman 搞清楚了这些能量球的规律。首先,能量球上面有一个正整数 N,运用激发手段可以使得能量球上的正整数变为原来的数的一个真因子(A 是 B 的一个真因子,等价于 B 是 A 的整数倍且 0<A<B),并且放出单位数量的 能量。当然,变为哪一个真因子是可以自由选择的。现在 sideman 想知道每颗能 量球最多可以放出多少能量,以及有多少种方式达到这个目的(两种操作方式被 认为是不同的,当且仅当它们的操作序列中存在不同的真因子)。
为了帮助 sideman 返回家乡,这个问题就交给你了。
【输入文件】:
输入文件包含多组测试数据。每组测试数据包含一个正整数 N,表示要计算
的能量球。输入文件以 EOF 结束。
【输出文件】:
对于每组测试数据,在单独的一行内输出两个正整数,分别表示最多能够放
出的能量值和方案数。
【输入输出样例】:
enb.in
2
6
enb.out
1 1
2 2
【样例说明】
6 有两种方式:3,1 和 2,1,这两种方式都可以放出两个单位的能量。
【数据规模】:
对于 30% 的数据,保证 N≤1000。
对于 100% 的数据,保证 N≤10^9,测试数据不多于 100 组。
考试得分: 0
主要算法 : 质数(质因数分解,质数算术基本定理)
题干:
类质因数分解模型
应试策略:
运用记忆化搜索,搜出每一个数对应的方案数与能量数,在记忆化调用就可以比较a1来进行排序
代码
#include<math.h> #include<stdio.h> #include<stdlib.h> #define FORa(i,s,e) for(int i=s;i<=e;i++) #define FORs(i,s,e) for(int i=s;i>=e;i--) #define File(name) freopen(name".in","r",stdin),freopen(name".out","w",stdout) using namespace std; const int N=31624; int n; struct Node{ int power,cnt; }a[N+1]; Node Dfs(int x) { if(a[x].cnt) return a[x]; Node fp; FORa(i,1,sqrt(x)) { if(x%i==0) { if(i!=1) { fp=Dfs(x/i); if(fp.power+1==a[x].power) a[x].cnt+=fp.cnt; if(fp.power+1>a[x].power) a[x].power=fp.power+1,a[x].cnt=fp.cnt; } fp=Dfs(i); if(fp.power+1==a[x].power) a[x].cnt+=fp.cnt; if(fp.power+1>a[x].power) a[x].power=fp.power+1,a[x].cnt=fp.cnt; } } return a[x]; } int main() { File("enb"); a[1].cnt=1; while(scanf("%d",&n)==1) { Dfs(n); printf("%d %d\n",a[n].power,a[n].cnt); } return 0; }
非完美算法:
有了记忆化搜索就会有DP
正解:
1.质因数分解,得出质数的幂次和为能量数
2.假设每一个分解出的质因子都是不一样的,则方案数为质数的幂次和的阶乘
3.但是这有一些是一样的,所以只有将重复的排除才行,怎么排除呢?
4.一个一样的质因子可在其中的组合数为此质因子出现的次数的阶乘,则将方案数除以所有质因子出现的次数的阶乘的积即可
总结:
1.质数算术基本定理
2.将路径转化为质因数乘积的形式