暂无链接
分解
【题目描述】
给定正整数N,你需要将其分解为若干正整数的乘积,要求分解出的数之间
相差都不超过1。
【输入格式】
第一行一个正整数T,表示数据组数。
接下来T 行,每行一个正整数N,意义如题面所示。
【输出格式】
对于每组数据,首先输出一行,一个整数P,表示有几组可行解,如果有无穷
多组解,输出-1。
若没有无穷多组解,接下来输出P 行,每行首先输出一个正整数M,表示将
N 分解为几个数,接下来输出M 个数,表示分解出的数。
如有多组解,请将分解出的数字从小到大排序,记为序列
c1c2...cM
c
1
c
2
.
.
.
c
M
,按照该
序列的字典序,将解从小到大输出。
一组解分解出多个数时,请先输出较小的数。
【样例输入】
2
1
12
【样例输出】
-1
3
3 2 2 4
2 3 4
1 12
【数据范围】
对于20%的数据 N≤100
对于40%的数据 N≤
109
10
9
对于100%的数据 N≤
1018
10
18
,T≤10
题解
当时看错题了,以为分出的因数从小到大相邻两个之间差不大于一。。。果断爆零。
然而,真正的题意是分解出的因数极差不大于一。。。orz瞬间变普及。
所以我们枚举质因数个数,每次先填充对应的次方根,然后根据当前因数乘积填充次方根+1,可以说是非常暴力了。
-1的情况就是 2n 2 n 或者0。
另外,开n次方根的时候可以用pow函数,但是指数记得用long double,其他各种地方都开long long,毒瘤出题人。。。
代码
#include<bits/stdc++.h>
#define ll unsigned long long
using namespace std;
ll pow2[64],n,cot,hh[64][64];
void in()
{scanf("%lld",&n);}
void work(int x)
{
ll base=(ll)pow(n,(double)1/x);
ll ans[64],pro=1;
for(int i=1;i<=x;++i)
ans[i]=base,pro*=base;
for(int i=x;i>=1;--i)
{
if(pro==n)break;
pro/=base;
pro*=base+1;
ans[i]++;
}
if(pro!=n)return;
cot++;
hh[cot][0]=x;
for(int i=1;i<=x;++i)
hh[cot][i]=ans[i];
}
void ac()
{
cot=0;
if(!n||n==1)
{
printf("-1\n");
return;
}
for(int i=62;i>=1;--i)
if(n==pow2[i])
{
printf("-1\n");
return;
}
for(int i=62;i>=1;--i)
work(i);
printf("%lld\n",cot);
for(int i=1;i<=cot;++i)
{
for(int j=0;j<=hh[i][0];++j)
printf("%lld ",hh[i][j]);
putchar(10);
}
}
int main()
{
pow2[0]=1;
for(int i=1;i<=63;++i)
pow2[i]=pow2[i-1]*2;
int T;
scanf("%d",&T);
for(int i=1;i<=T;++i)
in(),ac();
return 0;
}