题目:
小利迪亚喜欢玩数字。今天她有一个正整数n,她想分解它是正整数的产物。
由于Lidia很少,她喜欢玩数字没有什么区别。所以,所有的数字
分解应该最多相差一个。当然,在所有数字的产品
分解必须等于n。她认为两个分解相同,当且仅当它们相同
具有相同数量的整数,并且有一个将第一个转换为第二个的置换
一。
写一个程序,找到所有的分解,这是Lidia今天可以玩的。
Input:
输入的唯一一行包含一个整数n(1≤n≤1e18)。
Output:
在第一行输出n的分解数,如果这个数是无限的,则输出-1。如果号码的分解是有限的,每行打印一个。在每一行中首先打印数字ki
元素分解。然后打印ki整数在任何顺序分解。别忘了
仅仅按元素顺序不同的分解被认为是相同的。
Examples
input:
12
output:
3
1 12
3 2 3
2 2 3 3
input:
1
output:
-1
这个题目原来是这样的,
后来这题改了,只要输出个数即可。就是上述示例Output第一行。
但是我们做题时:因为改了题目,题目读出来很多意思
因为当时的题目有几行一直干扰着我们队。
只到杨哥哥他们队做出来后,回去告诉我们才知道正确的题意是什么。
题意:
主人公小L,她喜欢数字N,想把它分解,且分出来的数字一定要是相差值<=1的.
比如 12=3×4, 12=2×2×3; 12=12;
为什么12=12呢,其实这是考虑到质数的情况,你看质数没有因子,只有1和它本身,
要是你说它本身都不算吗?那一个数总有它的分解方法吧!
(以上都是瞎扯 和 题目扯在一起)。管他呢反正就是最后就是+1;
题解:
第一种情况:
题目提到了如果有无限个分解方法就要输出-1.
1的确是一种情况,1=1,1=1×1,1=1×1×1................
4也是:
4=2×2,4=2×2×1,4=2×2×1×1, 4=2×2×1×1×1.........
所以2的次方都满足题意,且的确是无限个分法。
第二种情况:
(拿36为例子)
分三部分:A、B、C ans=A+B+C
A 36=2×2×3×3, 36=3×3×4;
B 36=6×6
C 36=36
A、部分就是:
正儿八经地符合题意,只要枚举两个数 i , i+1
把tmp=n, 将 i ,(i+1)(前提是能整除)来除tmp,只要当tmp==1就满足A的情况。
B、就是判断:
可能是两个数一模一样或者相差1吧,两个数的乘积==N
这时需要判断 t=sqrt(n);
n==t*t n==t*(t-1) n==t*(t+1);
只要满足一个就可以ans++;
C、一开始就提到可能是本身无需分解。ans++;
理论现行——算复杂度:对于B,C两部分就是O(1),对于A部分对于1e18的数据有点牵强,但是认真想一想要是满足第一种情况肯定是 3个或者以上的 i 或者 i+1相乘。
所以这个复杂度应该是 根号三的N 对于1e18->1e6的复杂度。游刃有余。
最后贴上代码,主要是https://blog.csdn.net/axuhongbo/article/details/78570773
还有杨哥哥的“热心讲解”。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll n;
scanf("%lld",&n);
ll ans=0,tmp=n;
while(tmp%2==0){
tmp>>=1;
}if(tmp==1){
return 0*printf("-1\n");
}
for(ll i=2;i*i*i<=n;i++){
if(n%i==0){
tmp=n;
while(tmp%i==0){
tmp/=(i);
}
while(tmp%(i+1)==0){
tmp/=(i+1);
}
if(tmp==1){
ans++;
}
}
}
ll t=sqrt(n);
if(t*t==n){
ans++;
}else if((t+1)*t==n){
ans++;
}else if((t-1)*t==n){
ans++;
}
printf("%lld\n",ans+1);
return 0;
}