[UESTC SC T2] 分解

暂无链接

分解

【题目描述】

给定正整数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
#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;
}

你可能感兴趣的:(数论&数学========)