Gym 100801D Distribution in Metagonia (数学思维题)

题目:传送门。(需要下载PDF)

题意:t组数据,每组数据给定一个数ni(1 ≤ ni ≤ 10^18),把ni拆成尽可能多的数,要求每个数的素因子只包含2和3,且这些数不能被彼此整除,输出一共能拆成多少个数,并输出这些数。

题解:根据题意ni = 2^a0*3^b0*+2^a1*3^b1+........+2^ax*3^bx,所以我们按照ai升序bi降序的顺序求出每一个加数,这样会保证这些数不能被彼此整除。首先打表得知3^40会超过long long,3^39不会,先打出3^39的表存到数组中,然后循环遍历即可,代码中的tmp表示的是2^ai

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
ll num3[50];
ll ans[105];
int main()
{
    freopen("distribution.in","r",stdin);
    freopen("distribution.out","w",stdout);
    num3[0]=1;
    for(int i=1;i<=39;i++)
    num3[i]=num3[i-1]*3;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(ans,0,sizeof(ans));
        ll n,m;
        ll cnt=0;
        scanf("%lld",&n);
        ll tmp=1;
        int b=39;
        while(n)
        {
            while(n%2==0&&n>0) //n%2==0才是偶数
            {
                n/=2;
                tmp*=2;
            }
            while(b>=0)
            {
                if(num3[b]>n)
                b--;
                else
                {
                    n-=num3[b];
                    ans[cnt++]=tmp*num3[b];
                    break;
                }
            }

            //cout<<"bb"<<n<<endl;
        }
        cout<<cnt<<endl;
        for(int i=0;i<cnt-1;i++)
        cout<<ans[i]<<" ";
        cout<<ans[cnt-1]<<endl;
    }
    return 0;
}

 

posted @ 2016-08-08 14:18  Ritchie丶  阅读(390)  评论(0编辑  收藏  举报