https://ac.nowcoder.com/acm/contest/318/E

C++版本一

题解:

这是一个考验数学思维的题目。
当满足条件的集合内只有两个数的时候,要么n=a*a,要么n=a*(a-1),我们可以直接对n进行开根号运算,令cnt1 = ceil(sqrt(n)),cnt2 = floor(sqrt(n)),然后判断cnt1 *cnt2 是否等于n即可。当满足条件的集合内有大于等于三个数的时候,我们可以知道n = a * a * a * ... * (a-1)*...*(a-1)。当a取到最大值时,应该满足n = a * a * a,而n是小于等于1e18的,所以我们可以知道a是小于等于1e6的,所以我们就可以暴力对a进行枚举了,每次验证一下是否合法即可。
对于输出“-1”的情况,也就只有当n=1,或者n=2^k的时候会成立,此时n可以分解为k个2和无数个1相乘的形式,故有无数个集合。最后再按要求处理一下输出就可以了。

#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define IOS ios::sync_with_stdio(false)
#define ***(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;
const int MX = 1e6 + 5;
const int N = 1e6;

vector<ll> ver[MX];

int main() {
    // FIN;
    int cas = 1;
    ll n; int T;
    cin >> T;
    while (T--) {
        scanf("%lld", &n);
        bool flag = 1;
        for (int i = 0; i < 64; i++) {
            if ((1ll << i) == n) {
                flag = 0;
                break;
            }
        }
        printf("Case #%d:\n", cas++);
        if (!flag) {
            puts("-1");
            continue;
        }
        ver[0].pb(n);
        int num = 1;
        ll cnt = (ll)sqrt(n);
        if (cnt * cnt == n) {
            ver[num].pb(cnt);
            ver[num].pb(cnt);
            num++;
        }
        if (cnt * (cnt + 1) == n) {
            ver[num].pb(cnt);
            ver[num].pb(cnt + 1);
            num++;
        }
        for (int i = 2; i <= N; i++) {
            if (i == cnt) continue;
            if ((ll)i * i * i > n) break;
            ll now = n;
            int num1 = 0, num2 = 0;
            if (now % i == 0) {
                while (now % i == 0) now /= i, num1++;;
                while (now % (i + 1) == 0) now /= (i + 1), num2++;
                if (now == 1 && num1 > 0) {
                    for (int j = 0 ; j < num1; j++) ver[num].pb(i);
                    for (int j = 0; j < num2; j++) ver[num].pb(i + 1);
                    num++;
                }
            }
        }
        for (int i = 0; i < num; i++) {
            for (int j = i + 1; j < num; j++) {
                if (ver[i].size() > ver[j].size()) swap(ver[i], ver[j]);
            }
        }
        printf("%d\n", num);
        for (int i = 0; i < num; i++) {
            int sz = ver[i].size();
            printf("%d ", sz);
            for (int j = 0; j < sz; j++)
                printf("%lld%c", ver[i][j], " \n"[j == sz - 1]);
            ver[i].clear();
        }
    }
    return 0;
}

C++版本二 

#include <iostream>
#include<stdio.h>
#include <string.h>
#include<set>
#include<bits/stdc++.h>
using namespace std;
struct node
{
    long long  a,b,c,d;
};
node s[105];
void init()
{
    for(int i=0;i<105;i++)
    {
        s[i].a=-1;
        s[i].b=-1;
        s[i].c=-1;
        s[i].d=-1;
    }
}
int main()
{
    int t;
    cin>>t;
   long long  x;
 
    for(int cas=1; cas<=t; cas++)
    {
        int flag=1;
       init();
        scanf("%lld",&x);
 
        long long yu=x;
        printf("Case #%d:\n",cas);
        if((yu&(yu-1))==0)
            flag=0;
 
        for(double i=2.0; i<=68.0; i=i+1.0)
        {
            long long num=x;
            long long num1=0,num2=0;
            long long p=(long long )(pow((double)x,1.0/i));
            long long q=(long long )(pow((double)x,1.0/i))+1;
            if(p==1)
                break;
            if(q==1)
                break;
            while(num%p==0)
                num/=p,num1++;
            while(num%q==0)
                num/=q,num2++;
            if(num==1)
            {
                int k=(int)i;
                s[k].a=(num1);
                s[k].b=(p);
                s[k].c=(num2);
                s[k].d=(q);
            }
        }
        int su=0;
 
        int biaoji[1000];
        memset(biaoji,0,sizeof(biaoji));
         if(flag)
        {
 
        for(int i=0; i<105; i++)
        {
            if((s[i].a!=-1||s[i].c!=-1)&&biaoji[s[i].a+s[i].c]==0)
            {
                su++;
 
                biaoji[s[i].a+s[i].c]=1;
 
            }
        }
        }
        memset(biaoji,0,sizeof(biaoji));
        if(flag)
        {
            printf("%d\n",su+1);
         printf("1 %lld\n",(long long )x);
        for(int i=0; i<105; i++)
        {
            if((s[i].a!=-1||s[i].c!=-1)&&biaoji[s[i].a+s[i].c]==0)
            {
                printf("%lld",s[i].a+s[i].c);
                biaoji[s[i].a+s[i].c]=1;
                for(int j=0; j<s[i].a; j++)
                    printf(" %lld",s[i].b);
                for(int j=0; j<s[i].c; j++)
                    printf(" %lld",s[i].d);
                printf("\n") ;
            }
        }
        }
        else
            printf("-1\n");
    }
 
}