user-0 提问: 一个算法关于递归

回复:
user: user-0
content: 引用 8 楼 zilaishuichina 的回复:如果一个质数是某个数的因数，那么就说这个质数是这个数的质因数  先说思路：  n = 0时，没有质因数，可以拿的糖果数为0 n = 1时，没有质因数，可以拿的糖果数为0 n = 2时，质因数为2，不大于√2的质因数没有，可以拿的糖果数为0 n = 3时，质因数为3，不大于√3的质因数没有，可以拿的糖果数为0 n = 4时，质因数为2，不大于√4的质因数为2，可以拿的糖果数为2 n = 5时，质因数为5，不大于√5的质因数没有，可以拿的糖果数为0 n = 6时，质因数为2，3，不大于√6的质因数为2，可以拿的糖果数为2 n = 7时，质因数为7，不大于√7的质因数没有，可以拿的糖果数为0  n = 8时，质因数为2，不大于√8的质因数为2，可以拿的糖果数为 2 加上  n=(8-2*2)时可以拿到的糖果的最大数2 n = 9时，质因数为3，不大于√9的质因数为3，可以拿的糖果数为 3 加上  n=(9-2*3)时可以拿到的糖果的最大数0 n = 10时，质因数为2，5，不大于√10的质因数为2，可以拿的糖果数为 2 加上  n=(10-2*2)时可以拿到的糖果的最大数2  即： 已知数字num的所有不大于√num的质因子为a1,a2,...,ai,...,an 则num个糖果中，最大可以拿的糖果数为： a1 + (num - a1 * 2)个糖果中最大可以拿的个数 a2 + (num - a2 * 2)个糖果中最大可以拿的个数 ... ai + (num - ai * 2)个糖果中最大可以拿的个数 ... an + (num - an * 2)个糖果中最大可以拿的个数 以上各行的和的最大值  则，当需要求num个糖果中，最大可以拿的糖果数，将0～（num-1）分别能拿多少个求出来，num有多少个不大于√num的质因数求出来，最大可以拿的糖果数就可以得到  贴代码  //判断n是否为质数  bool IsPrime(unsigned int n) { 	bool isPrime = true; 	for (unsigned int i = 2; i * i <= n; i++) 	{ 		if (n%i == 0) 		{ 			isPrime = false; 			break; 		} 	} 	return isPrime; } //计算√100000以内的所有质数，存入g_primes备用 //（实际有65个） unsigned int g_primes[100]; unsigned int g_count_primes = 0; void GetPrimes() { 	memset(g_primes, 0x00, sizeof(unsigned int)* 100); 	g_count_primes = 0; 	for (unsigned int i = 2; i * i <= 100000; i++) 	{ 		if (IsPrime(i)) 		{ 			g_primes[g_count_primes] = i; 			g_count_primes++; 		} 	} } //计算0～√num之间，num的质因数，存入g_primes_of_num //（√100000以内的所有质数最多65个，所以num的质因数最多65个） unsigned int g_primes_of_num[100]; unsigned int g_count_primes_of_num = 0; void GetPrimesOfNum(unsigned int num) { 	memset(g_primes_of_num, 0x00, sizeof(unsigned int)* 100); 	g_count_primes_of_num = 0;  	//试除法： 	//0～√num之间，用每一个质数g_primes[i]试除num 	//能除尽，则该质数g_primes[i]是num的一个不大于√num的质因数 	for (unsigned int i = 0; i < g_count_primes; i++) 	{ 		if (g_primes[i] * g_primes[i] <= num) 		{ 			if (num % g_primes[i] == 0) 			{ 				g_primes_of_num[g_count_primes_of_num] = g_primes[i]; 				g_count_primes_of_num++;  				//若g_primes[i]是num的一个不大于√num的质因数 				//将num中所有为g_primes[i]的质因子全部去掉 				while (num % g_primes[i] == 0) 				{ 					num = num / g_primes[i]; 				} 			} 		} 		else 		{ 			break; 		} 	} } //计算n = num时，最多可以拿多少个糖果，存入g_max_candy_of_num //（题目约定n<=100000） //已知数字num的所有不大于√num的质因子为a1,a2,...,ai,...,an //则num个糖果中，最大可以拿的糖果数candy为： //a1 + (num - a1 * 2)个糖果中最大可以拿的个数 //a2 + (num - a2 * 2)个糖果中最大可以拿的个数 //... //ai + (num - ai * 2)个糖果中最大可以拿的个数 //... //an + (num - an * 2)个糖果中最大可以拿的个数 //以上各行的和的最大值 unsigned int g_max_candy_of_num[100001]; void GetMaxCandy(unsigned int num) { 	GetPrimesOfNum(num);  	unsigned int max_candy = 0; 	for (unsigned int i = 0; i < g_count_primes_of_num; i++) 	{ 		unsigned int candy = g_primes_of_num[i] + g_max_candy_of_num[num - g_primes_of_num[i] * 2]; 		if (candy > max_candy) 		{ 			max_candy = candy; 		} 	} 	g_max_candy_of_num[num] = max_candy; } //分别计算糖果数为0-n时，各最多可以拿多少个糖果 unsigned int GetCandies(unsigned int n) { 	g_max_candy_of_num[0] = 0; // n = 0时，可以拿的糖果数为0 	g_max_candy_of_num[1] = 0; // n = 1时，可以拿的糖果数为0 	g_max_candy_of_num[2] = 0; // n = 2时，可以拿的糖果数为0 	g_max_candy_of_num[3] = 0; // n = 3时，可以拿的糖果数为0 	for (unsigned int i = 4; i <= n; i++) 	{ 		GetMaxCandy(i); 	} 	return g_max_candy_of_num[n]; }  int main(int argc, char* argv[]) { 	//预算质数数组 	GetPrimes();  	//求糖果数 	unsigned int num = 15; 	printf("n = %u, candy = %u\n", num, GetCandies(num)); 	num = 100; 	printf("n = %u, candy = %u\n", num, GetCandies(num)); 	num = 1000; 	printf("n = %u, candy = %u\n", num, GetCandies(num)); 	num = 68467; 	printf("n = %u, candy = %u\n", num, GetCandies(num));  	return 0; }   输出 n = 15, candy = 6 n = 100, candy = 50 n = 1000, candy = 500 n = 68467, candy = 34232  谢谢啊很详细明白了

user: user-1
content: http://blog.csdn.net/reidsc/article/details/54845800

user: user-2
content: 如果一个质数是某个数的因数，那么就说这个质数是这个数的质因数  先说思路：  n = 0时，没有质因数，可以拿的糖果数为0 n = 1时，没有质因数，可以拿的糖果数为0 n = 2时，质因数为2，不大于√2的质因数没有，可以拿的糖果数为0 n = 3时，质因数为3，不大于√3的质因数没有，可以拿的糖果数为0 n = 4时，质因数为2，不大于√4的质因数为2，可以拿的糖果数为2 n = 5时，质因数为5，不大于√5的质因数没有，可以拿的糖果数为0 n = 6时，质因数为2，3，不大于√6的质因数为2，可以拿的糖果数为2 n = 7时，质因数为7，不大于√7的质因数没有，可以拿的糖果数为0  n = 8时，质因数为2，不大于√8的质因数为2，可以拿的糖果数为 2 加上  n=(8-2*2)时可以拿到的糖果的最大数2 n = 9时，质因数为3，不大于√9的质因数为3，可以拿的糖果数为 3 加上  n=(9-2*3)时可以拿到的糖果的最大数0 n = 10时，质因数为2，5，不大于√10的质因数为2，可以拿的糖果数为 2 加上  n=(10-2*2)时可以拿到的糖果的最大数2  即： 已知数字num的所有不大于√num的质因子为a1,a2,...,ai,...,an 则num个糖果中，最大可以拿的糖果数为： a1 + (num - a1 * 2)个糖果中最大可以拿的个数 a2 + (num - a2 * 2)个糖果中最大可以拿的个数 ... ai + (num - ai * 2)个糖果中最大可以拿的个数 ... an + (num - an * 2)个糖果中最大可以拿的个数 以上各行的和的最大值  则，当需要求num个糖果中，最大可以拿的糖果数，将0～（num-1）分别能拿多少个求出来，num有多少个不大于√num的质因数求出来，最大可以拿的糖果数就可以得到  贴代码  //判断n是否为质数  bool IsPrime(unsigned int n) { 	bool isPrime = true; 	for (unsigned int i = 2; i * i <= n; i++) 	{ 		if (n%i == 0) 		{ 			isPrime = false; 			break; 		} 	} 	return isPrime; } //计算√100000以内的所有质数，存入g_primes备用 //（实际有65个） unsigned int g_primes[100]; unsigned int g_count_primes = 0; void GetPrimes() { 	memset(g_primes, 0x00, sizeof(unsigned int)* 100); 	g_count_primes = 0; 	for (unsigned int i = 2; i * i <= 100000; i++) 	{ 		if (IsPrime(i)) 		{ 			g_primes[g_count_primes] = i; 			g_count_primes++; 		} 	} } //计算0～√num之间，num的质因数，存入g_primes_of_num //（√100000以内的所有质数最多65个，所以num的质因数最多65个） unsigned int g_primes_of_num[100]; unsigned int g_count_primes_of_num = 0; void GetPrimesOfNum(unsigned int num) { 	memset(g_primes_of_num, 0x00, sizeof(unsigned int)* 100); 	g_count_primes_of_num = 0;  	//试除法： 	//0～√num之间，用每一个质数g_primes[i]试除num 	//能除尽，则该质数g_primes[i]是num的一个不大于√num的质因数 	for (unsigned int i = 0; i < g_count_primes; i++) 	{ 		if (g_primes[i] * g_primes[i] <= num) 		{ 			if (num % g_primes[i] == 0) 			{ 				g_primes_of_num[g_count_primes_of_num] = g_primes[i]; 				g_count_primes_of_num++;  				//若g_primes[i]是num的一个不大于√num的质因数 				//将num中所有为g_primes[i]的质因子全部去掉 				while (num % g_primes[i] == 0) 				{ 					num = num / g_primes[i]; 				} 			} 		} 		else 		{ 			break; 		} 	} } //计算n = num时，最多可以拿多少个糖果，存入g_max_candy_of_num //（题目约定n<=100000） //已知数字num的所有不大于√num的质因子为a1,a2,...,ai,...,an //则num个糖果中，最大可以拿的糖果数candy为： //a1 + (num - a1 * 2)个糖果中最大可以拿的个数 //a2 + (num - a2 * 2)个糖果中最大可以拿的个数 //... //ai + (num - ai * 2)个糖果中最大可以拿的个数 //... //an + (num - an * 2)个糖果中最大可以拿的个数 //以上各行的和的最大值 unsigned int g_max_candy_of_num[100001]; void GetMaxCandy(unsigned int num) { 	GetPrimesOfNum(num);  	unsigned int max_candy = 0; 	for (unsigned int i = 0; i < g_count_primes_of_num; i++) 	{ 		unsigned int candy = g_primes_of_num[i] + g_max_candy_of_num[num - g_primes_of_num[i] * 2]; 		if (candy > max_candy) 		{ 			max_candy = candy; 		} 	} 	g_max_candy_of_num[num] = max_candy; } //分别计算糖果数为0-n时，各最多可以拿多少个糖果 unsigned int GetCandies(unsigned int n) { 	g_max_candy_of_num[0] = 0; // n = 0时，可以拿的糖果数为0 	g_max_candy_of_num[1] = 0; // n = 1时，可以拿的糖果数为0 	g_max_candy_of_num[2] = 0; // n = 2时，可以拿的糖果数为0 	g_max_candy_of_num[3] = 0; // n = 3时，可以拿的糖果数为0 	for (unsigned int i = 4; i <= n; i++) 	{ 		GetMaxCandy(i); 	} 	return g_max_candy_of_num[n]; }  int main(int argc, char* argv[]) { 	//预算质数数组 	GetPrimes();  	//求糖果数 	unsigned int num = 15; 	printf("n = %u, candy = %u\n", num, GetCandies(num)); 	num = 100; 	printf("n = %u, candy = %u\n", num, GetCandies(num)); 	num = 1000; 	printf("n = %u, candy = %u\n", num, GetCandies(num)); 	num = 68467; 	printf("n = %u, candy = %u\n", num, GetCandies(num));  	return 0; }   输出 n = 15, candy = 6 n = 100, candy = 50 n = 1000, candy = 500 n = 68467, candy = 34232

user: user-3
content: 引用 6 楼 qq_36151474 的回复:[quote=引用 5 楼 user-3的回复:]恩，算法应该是对的，但这是穷举法，所以时间复杂度不能满足需要 这个题应该可以利用动态规划求解，因为在穷举过程中有很多数据是重复计算的，针对同一个数会调用getcandy很多次，可以想办法把这些中间结果保存起来，计算后面的数时直接利用前面的结果，具体的代码还没写好 谢谢了，我以为我用的就是动态规划分而治之把大往小化的思想，结果好像还真的又成了枚举，那麻烦你能不能根据我的这个策略改下然后贴出来想学习下谢谢了。[/quote] 前面3楼贴出来的代码就是用的枚举法啊，跟你的策略是一样的，只是你的算法有点儿小错误，我的就是根据你的改的，动态规划的算法还没想好，等想好了发你吧

user: user-0
content: 引用 5 楼 user-3的回复:恩，算法应该是对的，但这是穷举法，所以时间复杂度不能满足需要 这个题应该可以利用动态规划求解，因为在穷举过程中有很多数据是重复计算的，针对同一个数会调用getcandy很多次，可以想办法把这些中间结果保存起来，计算后面的数时直接利用前面的结果，具体的代码还没写好 谢谢了，我以为我用的就是动态规划分而治之把大往小化的思想，结果好像还真的又成了枚举，那麻烦你能不能根据我的这个策略改下然后贴出来想学习下谢谢了。

user: user-3
content: 恩，算法应该是对的，但这是穷举法，所以时间复杂度不能满足需要 这个题应该可以利用动态规划求解，因为在穷举过程中有很多数据是重复计算的，针对同一个数会调用getcandy很多次，可以想办法把这些中间结果保存起来，计算后面的数时直接利用前面的结果，具体的代码还没写好

user: user-0
content: 引用 3 楼 user-3的回复:[quote=引用 2 楼 qq_36151474 的回复:] [quote=引用 1 楼 cyfcsd 的回复:] 你试试这个代码 #include<iostream> #include<cmath> using namespace std;   //判断是否为质数  bool judge(int n) {     for(int i=2;i*i<=n;i++)     {         if(n%i==0) 		{             return false;         }     }     return true; } int max1=-1; //递归求解  int getcandy(int m) {     //出口边界      if(m<4||judge(m))     {         return 0;     }     //把所有满足条件做比较取相对于全局最优解      for(int i=2;i*i<=m;i++)     { 		int b = 0;         if(m%i==0&&judge(i))         {             b=getcandy(m-i-i)+i;         } 		if(max1<b)         {              max1=b;         }     }     //得到最优的解      return max1; }   int main() {     int m;     cin>>m;     cout<<getcandy(m)<<endl; 	system("pause");     return 0; }  抱歉还是不对 输入100应该得50 我的代码结果内存不崩溃但是没有结果 你的代码有结果但是不正确[/quote]  引用 2 楼 qq_36151474 的回复:[quote=引用 1 楼 cyfcsd 的回复:] 你试试这个代码 #include<iostream> #include<cmath> using namespace std;   //判断是否为质数  bool judge(int n) {     for(int i=2;i*i<=n;i++)     {         if(n%i==0) 		{             return false;         }     }     return true; } int max1=-1; //递归求解  int getcandy(int m) {     //出口边界      if(m<4||judge(m))     {         return 0;     }     //把所有满足条件做比较取相对于全局最优解      for(int i=2;i*i<=m;i++)     { 		int b = 0;         if(m%i==0&&judge(i))         {             b=getcandy(m-i-i)+i;         } 		if(max1<b)         {              max1=b;         }     }     //得到最优的解      return max1; }   int main() {     int m;     cin>>m;     cout<<getcandy(m)<<endl; 	system("pause");     return 0; }  抱歉还是不对 输入100应该得50 我的代码结果内存不崩溃但是没有结果 你的代码有结果但是不正确[/quote] 奥奥，错了，你把那个max1的定义放到getcandy函数里面试试[/quote] 还是不对输入一些数字能够得出正确结果但是输入1000,68467等数字还是无法得出结果，内存不报错但就是不出结果。

user: user-3
content: 引用 2 楼 qq_36151474 的回复:[quote=引用 1 楼 cyfcsd 的回复:] 你试试这个代码 #include<iostream> #include<cmath> using namespace std;   //判断是否为质数  bool judge(int n) {     for(int i=2;i*i<=n;i++)     {         if(n%i==0) 		{             return false;         }     }     return true; } int max1=-1; //递归求解  int getcandy(int m) {     //出口边界      if(m<4||judge(m))     {         return 0;     }     //把所有满足条件做比较取相对于全局最优解      for(int i=2;i*i<=m;i++)     { 		int b = 0;         if(m%i==0&&judge(i))         {             b=getcandy(m-i-i)+i;         } 		if(max1<b)         {              max1=b;         }     }     //得到最优的解      return max1; }   int main() {     int m;     cin>>m;     cout<<getcandy(m)<<endl; 	system("pause");     return 0; }  抱歉还是不对 输入100应该得50 我的代码结果内存不崩溃但是没有结果 你的代码有结果但是不正确[/quote]  引用 2 楼 qq_36151474 的回复:[quote=引用 1 楼 cyfcsd 的回复:] 你试试这个代码 #include<iostream> #include<cmath> using namespace std;   //判断是否为质数  bool judge(int n) {     for(int i=2;i*i<=n;i++)     {         if(n%i==0) 		{             return false;         }     }     return true; } int max1=-1; //递归求解  int getcandy(int m) {     //出口边界      if(m<4||judge(m))     {         return 0;     }     //把所有满足条件做比较取相对于全局最优解      for(int i=2;i*i<=m;i++)     { 		int b = 0;         if(m%i==0&&judge(i))         {             b=getcandy(m-i-i)+i;         } 		if(max1<b)         {              max1=b;         }     }     //得到最优的解      return max1; }   int main() {     int m;     cin>>m;     cout<<getcandy(m)<<endl; 	system("pause");     return 0; }  抱歉还是不对 输入100应该得50 我的代码结果内存不崩溃但是没有结果 你的代码有结果但是不正确[/quote] 奥奥，错了，你把那个max1的定义放到getcandy函数里面试试

user: user-0
content: 引用 1 楼 cyfcsd 的回复:你试试这个代码 #include<iostream> #include<cmath> using namespace std;   //判断是否为质数  bool judge(int n) {     for(int i=2;i*i<=n;i++)     {         if(n%i==0) 		{             return false;         }     }     return true; } int max1=-1; //递归求解  int getcandy(int m) {     //出口边界      if(m<4||judge(m))     {         return 0;     }     //把所有满足条件做比较取相对于全局最优解      for(int i=2;i*i<=m;i++)     { 		int b = 0;         if(m%i==0&&judge(i))         {             b=getcandy(m-i-i)+i;         } 		if(max1<b)         {              max1=b;         }     }     //得到最优的解      return max1; }   int main() {     int m;     cin>>m;     cout<<getcandy(m)<<endl; 	system("pause");     return 0; }  抱歉还是不对 输入100应该得50 我的代码结果内存不崩溃但是没有结果 你的代码有结果但是不正确

user: user-3
content: 你试试这个代码 #include<iostream> #include<cmath> using namespace std;   //判断是否为质数  bool judge(int n) {     for(int i=2;i*i<=n;i++)     {         if(n%i==0) 		{             return false;         }     }     return true; } int max1=-1; //递归求解  int getcandy(int m) {     //出口边界      if(m<4||judge(m))     {         return 0;     }     //把所有满足条件做比较取相对于全局最优解      for(int i=2;i*i<=m;i++)     { 		int b = 0;         if(m%i==0&&judge(i))         {             b=getcandy(m-i-i)+i;         } 		if(max1<b)         {              max1=b;         }     }     //得到最优的解      return max1; }   int main() {     int m;     cin>>m;     cout<<getcandy(m)<<endl; 	system("pause");     return 0; }