【CQBZOJ - 1205】因式分解问题
@因式分解问题@
- @因式分解问题@
- @写在前面@
- @题目描述@
- @算法1:DFS-原地爆炸瞬间TLE@
- @算法1.5:DFS优化-然而并没有什么不同@
- @算法2:部分记忆化 - 只是用来骗部分分@
- @算法3:正确的DP方法.jpg@
- @算法4:这才是正解好吧@
- @正确的代码打开方式@
- @有些中二的小结 ̄ω ̄=@
- @END-OF-ALL@
@写在前面@
掐指一算,因式分解问题应该是我思考时长最久的一道题。
但这没关系,我靠着自己坚定的步伐,一步一步的,将这道题斩在了前进的道路上,狠狠地。我并没有借助外部的力量:像是正解博客、或是已做出的同学。
我靠着自己的力量。我坚信:我可以做到。【中二少年!是你!】
尽管我的做法不是最优算法,但是,写写博客让大家知道我的心路历程,也挺好。
@题目描述@
将大于1的自然数N进行因式分解,满足 N=∏mi=1aiN=∏i=1maiN = \prod_{i=1}^{m}a_i 编一个程序,对任意的自然数N,求N的所有形式不同的因式分解方案总数。
例如,N=12,共有8种分解方案,分别是:12 = 12 = 6*2 = 4*3 = 3*4 = 3*2*2 = 2*6 = 2*3*2 = 2*2*3
输入
第1行:1个正整数N(N<=10^9)
输出
第1行:一个整数,表示N的因式分解方案总数
样例输入
12
样例输出
8
@算法1:DFS-原地爆炸瞬间TLE@
第一反应:构造所有方案数。
实现过程非常简单:枚举2~n内n的因子i,将它放在当前一位上,递归枚举n/i。
想想当初的自己也是天真,居然天真地以为这样的算法非常高大上,肯定是个优美的正解……然后用高大上的写法写出来后发现并不是那样的。
而是这样的:
“输入10910910^9”
“等待一秒……”
“等待两秒……”
“等待三秒……”
“栈溢出警告”
“程序关闭”
“内心OS:(╯‵□′)╯︵┻━┻”
DFS果然是很优美地……超时了。
int dfs(int n)
{int k=0;if(n==1) return 1;for(int i=n;i>=2;i--){if(n%i) continue;k+=dfs(n/i);}return k;
}//错误的示范方法
@算法1.5:DFS优化-然而并没有什么不同@
那时的我思考了一刻,突然!脑袋一亮【并不】想到一种优化!枚举因子的时候,可以枚举n/2n/2n/2~n−−√n\sqrt{n}之间的因子iii,然后得到n/i" role="presentation" style="position: relative;">n/in/in/i这个因子。这样,原本寻找因子的时间O(nnn)霎时间就变成了O(n" role="presentation" style="position: relative;">n−−√n\sqrt{n})!!!
我的天啊我真是个天才啊哈哈!
……
……
……
“内心OS:这TM不可能啊为什么它还是TLE(▼ヘ▼#)”
int dfs(int n)
{int k=1;if(n==1) return 1;for(int i=n/2;i>=sqrt(n);i--){if(n%i) continue;if(n/i!=i) k+=dfs(n/i);//不要忘考虑平方根k+=dfs(i);}return k;
}//莫名其妙的无用优化
优化无法让错误的算法AC。
@算法2:部分记忆化 - 只是用来骗部分分@
学到DP时,再次看到了这道题,于是想到记忆化。
然而……然而更尬的问题出现了,10910910^9再怎么开数组也看不下啊!
(╯‵□′)╯︵┻━┻去你的我还以为我想出了正解!
于是聪明的我出了一记十分的机制的损招招式:只开一部分记忆化;另一部分如果超出了某个界限LIM,就用DFS。
啊哈哈我真是骗分达人【然而这不是比赛,部分分没用】
const int LIM=1000000;
int f[LIM+5];
int Function(int x)
{if( x <= LIM && f[x] != 0) return f[x];int res=1;for(int i=x/2;i>=sqrt(x);i--){if(x%i) continue;if(x/i!=i) res+=Function(x/i);//不要忘考虑平方根res+=Function(i);}if( x <= LIM ) f[x]=res;return res;
}//骗分专用:部分记忆化
@算法3:正确的DP方法.jpg@
通过观察估算,我们其实发现:状态数并不需要那么多。比方说:对于奇数而言,所有下标为偶数的状态是闲置着的,就会产生白白浪费了很多空间的情况。所以为了保证状态的高效存储——
使用动态数组vector存储,映射表map找到状态是否存在过
哇嘎嘎我真是机智!
map<int,int>m;
vector<long long>f;
long long Function(int x)
{if(x==1) return 0;if( m.count(x) ) return f[m[x]];long long res=1;for(int i=2;i<=sqrt(x);i++)if( x % i == 0) res+=Function(i);for(int i=sqrt(x);i>=2;i--)if( x % i == 0 && i != sqrt(x) ) res+=Function(x/i);m[x]=f.size();f.push_back(res);return res;
}//终于可以AC了
@算法4:这才是正解好吧@
总觉得用vector+map有些别扭,太动态了。
那可不可以在没有DP之前就找到所有合法且可利用的状态呢?
答案是:显然可以【虽然我也没看出来qwq】
从状态转移方程来讲,一个数的转移是由它的因数转移而来的。
而它的因数是由它的因数的因数转移而来的,总而言之也是它的因数
所以,我们为何不妨先预处理n的因数,再进行愉快地动规?
@正确的代码打开方式@
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int f[10005],g[10005],len;
void Find_Prime(int x)
{f[len]=1;for(int i=2;i<=sqrt(x);i++)if( x % i == 0) f[++len]=i;for(int i=len;i>=1;i--)if( f[i]*f[i]!=x ) f[++len]=x/f[i];f[++len]=x;
}//寻找n的因数
int Function(int x)//处理的是n的第x个因数
{if(g[x]) return g[x];for(int i=1;i<=x;i++)if( f[x] % f[i] == 0 )g[x]+=Function(lower_bound(f,f+len+1,f[x]/f[i])-f);
//因为因数序列是单调递增的,所以可以使用二分查找return g[x];
}
int main()
{int n;scanf("%d",&n);Find_Prime(n);g[0]=1;printf("%d\n",Function(len));return 0;
}//AC从不是目的,弄懂才是目的
@有些中二的小结 ̄ω ̄=@
如果说,人不遇到点什么困难,是不现实的
人总会遇到形形色色的难处,编程也是,因为我们并非圣贤,并非“生而知之者”
但是,如果遇到一点困难就退缩,遇到一道难题就四处查正解,如果不会自己动脑想问题,不去自己动脑想问题
那样的话,怎么会有自己攻克题目的自豪感?怎么不会充斥“一看题解就懂,然而自己想不出来的尴尬?”
正如标题所言:
你,我,在世界上的任何人
都不适合放弃
@END-OF-ALL@
就是这样,新的一天里,也请多多关照哦(ノω<。)ノ))☆.。~
【CQBZOJ - 1205】因式分解问题相关推荐
- python 最快 因式分解_python中怎么对一个数进行因式分解?
1.Python因式分解代码:import time # 对一个数进行因式分解 def factorization(num): factor = [] while num > 1: for i ...
- 数据库 1205 Error 'Lock wait timeout exceeded; try restarting transaction' on query
收到报警,mysql的从数据库在同步的过程出现问题,已停止同步. mysql> show slave status\G *************************** 1. row ** ...
- java分解因式_用JAVA因式分解 并以9=3×3格式输出
//输入一个数字,判断是否为素数,如果不是素数,请因式分解packagehomework;importjava.util.Scanner;publicclasshomework7{publicstat ...
- 最大公因数、最小公倍数、因式分解
最大公因数使用辗转相除法来求,最小公倍数则由这个公式来求: GCD * LCM = 两数乘积 解法最大公因数可以使用递回与非递回求解,因式分解基本上就是使用小于输入数的数值当作除数,去除以输入数值,如 ...
- HDU-4516 威威猫系列故事——因式分解 多项式分解
题意:给定一个多项式,对其进行因式分解. 解法:由于多项式每一项系数绝对值不超过1000,由于最后解的形式为(x-a)(x-b)(x-c)(x-d)(x-e)其中a*b*c*d*e一定是最后的常数项系 ...
- factor--符号矩阵的因式分解
[功能简介]求符号表达式的因式分解,此外还能对整数进行素数因子分解. [语法格式] 1.f=factor(n) 对整数n进行素数因子分解,返回包含n的素数因子的行向量. 2.factor(X) 对符号 ...
- 蓝桥杯-8-1因式分解(java)
算法提高 8-1因式分解 时间限制:10.0s 内存限制:256.0MB问题描述设计算法,用户输入合数,程序输出若个素数的乘积.例如,输入6,输出2*3.输入20,输出2*2*5.样例与上面的样例输入 ...
- NYOJ 70 阶乘因式分解(二)
阶乘因式分解(二) 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 给定两个数n,m,其中m是一个素数. 将n(0<=n<=2^31)的阶乘分解质因数,求其中 ...
- NYOJ 56 阶乘因式分解(一)
阶乘因式分解(一) 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 给定两个数m,n,其中m是一个素数. 将n(0<=n<=10000)的阶乘分解质因数,求其 ...
最新文章
- android 运动管理,使用 MotionLayout 管理运动和微件动画
- python做词云做文本处理_文本挖掘——python词云实现
- Android java.lang.UnsatisfiedLinkError
- 基于JSON的高级AJAX开发技术
- 功能强大的Windows PowerShell
- 构造方法重载 java 1615136407
- 漫步最优化三十九——Fletcher-Reeves法
- java二叉树算法_java构建二叉树算法
- mq系列传感器的程序_Cooper Instruments传感器定制解决方案
- 二分类数据集_玩转UCI心脏病二分类数据集 领学课笔记
- linux mysql远程连接
- hp cp1025 linux 驱动,惠普HP LaserJet CP1025 打印机驱动
- DHU 数据科学技术与应用【10】 第八次单元测验 时序与语音数据处理 答案
- Python中time.sleep(0.001)真的只等待1毫秒吗?
- tcpreplay的安装与使用
- python中新建标签页的三种方法
- Revit二开 VS附加Revit时闪退程序
- 使用region注释,将代码块收(折叠)起来
- 10款精选的后台管理系统,快来一起颤抖吧!
- 十大项目管理知识-相关方识别管理