解決這題思路就是從找到的合適的base開始,從大到小逐個計算其係數。
為什麼可以這樣設計演算法:
1、題目給出n = a0 + a1*p0 + a2*p0*p1 + a3*p0*p1*p2 + ... ,說明對於輸入的每一個n都可分解完,這是前提。
2、代碼中有函數deal()。它完成兩部分功能,第一就是找到合適的base,這個base是不大於輸入的n的,下一個base是要大於n的。因為大於n的base其係數肯定
為0,所以不用處理。
3、那麼,為什麼可以用deal()中的第二個for迴圈來得到每個base的係數呢?
這取決於每個base的特點:1、2、2*3、2*3*5、2*3*5*7、2*3*5*7*11...。比如n=123,它的最大base為2*3*5,我們用n%(2*3*5)得到到值一定小於7!這又是為啥呢?
如果大於7,那麼最大的base最小也得是2*3*5*7啦!這就證明了開始的處理是正確的。那麼,我們再假設計算到第k個base時是正確的。我們會有經過第k個base處理
後的資料一定小於第k個base,假設第k個base為2*3*5*7*11,處理後n=(2*3*5*7)*(0---11)。這就說明了第k-1個base的處理也一定是正確的!
4、至於輸出可參考output()函數。
5、細心的讀者可能會發現數組a已經溢出了,可是並不影響結果,因為計算時根本用不到那部分。題目會輸入的資料只是32位的。
AC代碼:
#include<iostream>using namespace std;const int prime[]={2,3,5,7,11,13,17,19,23,29,31,37,39,41,43,47,51,53,57,59}; //前20個素數 __int64 a[21]; //存放各個base,比如1、2*3、2*3*5、2*3*5*7... int b[21],rem; //數組存放各個base的個數,rem記錄輸入的資料不小於前一個base,小於後一個base的位置 void init() //計算各個base { a[0]=1; for(int i=1;i<=20;i++) { a[i]=a[i-1]*prime[i-1]; }}void deal(int n) //找到位置並計算每個base的個數 { int i; for(i=0;i<=20;i++) { if(a[i]<=n && a[i+1]>n) { rem=i; break; } } memset(b,0,sizeof(b)); for(i=rem;i>=0;i--) { b[i]=n/a[i]; n=n%a[i]; }}void output(int n) //輸出 { cout<<n<<" = "; for(int i=0;i<=rem;i++) { if(b[i]) { cout<<b[i]; for(int j=0;j<i;j++) { cout<<"*"<<prime[j]; } if(i!=rem) cout<<" + "; } } cout<<endl;} int main(){ init(); int n; while(cin>>n,n) { deal(n); output(n); } return 0;}