数的分割

 问题是这样的: 如何把一个自然数分割成M部分, 每一部分都是另一个自然数的N次方. 比如,如何把81分解成三个数的平方. 答案有三个: 81=64+16+1, 81=36+36+9, 81=49+16+16. 如何把7分成四个数, 答案也是三个, 4-1-1-1, 3-2-1-1, 2-2-2-1.

 

这个题使用递归算法来做不难, 我在学习模板编程的时候把它作为一道练习题来做的, 姑且也放在这里凑个数吧.

 

程序中主要是一个'template<int M, int N=1> Class Split'类, 用来把一个数分解为M个数的N次方,其他没什么太多需要解释的了, 下面给出完整程序, 其中还有一些注释, 如果有兴趣请自己看吧.

//

// Author: dgu

// Email:   gdyxgzy@hotmail.com

//

#include <iostream>
#include <vector>

using namespace std;

// to see if an integer can be splitted into M parts, each part is an integer's N-th order
template<int M, int N=1>
class Split
{
 int num;

 vector<vector<int> > split(int m, int n, int start)
 {
  vector<vector<int> > result;
  if(m<n || n<=0)
   return result;
  if(n==1)
  {
   if(IsRoot(m)==true)
    result.push_back(vector<int>(1, m));
   return result;
  }
  for(int i=start; i<=m/n; ++i)
  {
   if(IsRoot(i)==false)
    continue;
   
   vector<vector<int> > sub_split = split(m-i, n-1, i);

   for(int j=0; j<sub_split.size(); ++j)
   {
    vector<int> temp = sub_split[j];
    temp.push_back(i);
    result.push_back(temp);
   }
  }
  return result;
 };

 bool IsRoot(int x)
 {
  int low=1, high=x;
  while(low<=high)
  {
   int middle = (low+high)/2;
   int temp=1;
   //
   //Be careful of integer overflow if you do a high N!
   //For example, if you do N=5, and x=33044(1, 2, 3, 8) or x=17083(1, 2, 3, 7),
   //if you don't check integer overflow, it will report not found.
   //So, you have to use 'temp<=x && i<N' instead of simply using 'i<N'.
   //
   for(int i=0; temp<=x && i<N; ++i)
    temp *= middle;

   if(temp>x)
    high = middle-1;
   else if(temp==x)
    return true;
   else
    low = middle+1;
  }
  return false;
 };
public:
 Split() : num(1) {};
 Split(int x) : num(x) {};

 vector<vector<int> > operator()()
 {
  if(num<=1)
  {
   cout<<"invalid input, must be greater than 1."<<endl;
   return vector<vector<int> >();
  }
  else
   return split(num, M, 0);
 }
 vector<vector<int> > operator()(int x)
 {
  if(x<=1)
  {
   cout<<"invalid input, must be greater than 1."<<endl;
   return vector<vector<int> >();
  }
  else
   return split(x, M, 0);
 };
};

 

 

int main()
{
 int number;
 vector<vector<int> > result;

 // to see if 81 can be splitted into 4 integer's square
 number = 81;
 result = Split<3,2>(number)();

 if(result.size() >0)
 {
  cout<<number<<" can be splitted as: "<<endl;
  for(int i=0; i<result.size(); ++i)
  {
   vector<int> temp = result[i];
   for(int j=0; j<temp.size(); ++j)
    cout<<temp[j]<<',';
   cout<<endl;
  }
  cout<<endl;
 }
 else
  cout<<"No solution for "<<number<<"."<<endl;

 number = 33044;
 //to see if 33044 can be splitted into 4 integer's 5-th power
 result = Split<4,5>(number)();
 if(result.size() >0)
 {
  cout<<number<<" can be splitted as: "<<endl;
  for(int i=0; i<result.size(); ++i)
  {
   vector<int> temp = result[i];
   for(int j=0; j<temp.size(); ++j)
    cout<<temp[j]<<',';
   cout<<endl;
  }
  cout<<endl;
 }
 else
  cout<<"No solution for "<<number<<"."<<endl;

 number = 110;
 // to see if 110 can be splitted into 7 integer's cube
 result = Split<7,3>()(number);

 if(result.size() >0)
 {
  cout<<number<<" can be splitted as: "<<endl;
  for(int i=0; i<result.size(); ++i)
  {
   vector<int> temp = result[i];
   for(int j=0; j<temp.size(); ++j)
    cout<<temp[j]<<',';
   cout<<endl;
  }
  cout<<endl;
 }
 else
  cout<<"No solution for "<<number<<"."<<endl;

 number = 17;
 // if N=1, then this algorithm degraded into a simple program to devide M into N parts
 // and, this is the template's default mode .
 result = Split<5>()(number);

 if(result.size() >0)
 {
  cout<<number<<" can be splitted as: "<<endl;;
  for(int i=0; i<result.size(); ++i)
  {
   vector<int> temp = result[i];
   for(int j=0; j<temp.size(); ++j)
    cout<<temp[j]<<',';
   cout<<endl;
  }
 }
 else
  cout<<"No solution for "<<number<<"."<<endl;

 return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值