题面(from luogu)
神奇的四次方数
在你的帮助下,v神终于帮同学找到了最合适的大学,接下来就要通知同学了。在班级里负责联络网的是dm同学,于是v神便找到了dm同学,可dm同学正在忙于研究一道有趣的数学题,为了请dm出山,v神只好请你帮忙解决这道题了。
题目描述:将一个整数m分解为n个四次方数的和的形式,要求n最小。例如,m=706,706=5^4 +
3^4,则n=2。
输入格式:
一行,一个整数m。
输出格式:
一行,一个整数n。
输入样例#1:
706
输出样例#1:
2
数据范围:对于30%的数据,m<=5000;对于100%的数据,m<=100,000
题面分析
这是一道很典型的完全背包问题
首先,我们先把问题抽象一下
对一个数,我们要将其分解成多个四次方数,但是这些四次方数从那里来呢?
当然是自己生成了
但是对于这道题,我们只要求出其最大的范围即可了,
这个方面的思路也便是一重for循环,求出边界了
到这里,这道题目已经出来一半了了,因为我们找到了背包问题中所谓的“物品”了
当然,它并没有给出"价值"
这也是需要我们来思考的
但是在这里
这个"价值”不应该很像"花费”吗?
我们用一个数去拆分,在总的使用上面便是要+1的
这不就是“花费”吗?
现在,这道题目,我们已经完全的完成构思了,剩下的便是实践了
代码
#include <bits/stdc++.h>
using namespace std;
int f[100009];
int n;
int step;
int main()
{
memset(f,0x7f,sizeof(f)); //初始化,全部都是无穷大,便于查找最小的
cin>>n; //输入
for (int i = 1; i <= 20; i++) //寻找解的范围(最大的边界是在20^4之内的,所以我们只要枚举到20,其实还用不到)
if (i*i*i*i > n) //模拟一下
{
step = i - 1; //记录位置
break;
}
if (step*step*step*step == n) //判断一下特例
{
cout<<1;
return 0;
}
for (int i = 1; i <= step; i++) //初始化,所有的四次方数都只需要一步来凑
f[i*i*i*i] = 1;
//套完全背包的模板
for (int i = 1; i <= step; i++)
for (int j = i*i*i*i; j <= n; j++)
f[j] = min(f[j],f[j-i*i*i*i] + 1);
cout<<f[n]; //输出
return 0;
}
没有水印了,,,这辈子可能都没有了、、、、