题目:传送门。(需要下载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; }