一个数n的最少可以由多少个数的平方和组成

 1 bool is_sqrt(int n){
 2     for(int i=1;i<=sqrt(double(n));i++){
 3         if(i*i == n)
 4             return true;
 5     }
 6     return false;
 7 }
 8 int pow_number(int mp){
 9     int* a = new int[mp+1];
10     a[0] = 1;
11     a[1] = 1;
12     if(mp==1) return 1;
13     if(is_sqrt(mp))return 1;
14     //int min = 0x8FFFFFFF;
15     for(int i=2;i<=mp;++i)
16     {
17         if(is_sqrt(i)){
18             a[i]=1;
19             continue;
20         }
21         a[i] = a[1]+a[i-1];
22         for(int j=i-1;j>=i/2;--j){
23             a[i] = a[i]<(a[j]+a[i-j])?a[i]:(a[j]+a[i-j]);
24         }
25     }
26     int temp = a[mp];
27     delete[] a;
28     return temp;
29 }

利用动态规划。

转载于:https://www.cnblogs.com/zhang-wen/p/4796719.html

### 回答1: 以下是 C++ 代码实现: ```c++ #include <iostream> #include <cmath> #include <cstring> using namespace std; bool isPerfectSquare(long long n) { long long root = sqrt(n); return (root * root == n); } int main() { string s; cin >> s; int n = s.length(); int dp[n+1]; memset(dp, -1, sizeof(dp)); dp[0] = 0; for (int i = 1; i <= n; i++) { for (int j = i-1; j >= 0; j--) { if (s[j] == '0' && j == i-1) break; long long num = stoll(s.substr(j, i-j)); if (isPerfectSquare(num)) { if (dp[j] != -1) { if (dp[i] == -1) dp[i] = dp[j] + 1; else dp[i] = min(dp[i], dp[j] + 1); } } } } cout << dp[n] << endl; return 0; } ``` 首先,我们定义一个 `isPerfectSquare` 来判断一个是否为完全平方。这个函利用了 C++ 的 STL 中的 `sqrt` 函。 接着,我们使用动态规划来解决这个问题。我们定义一个一维组 `dp`,其中 `dp[i]` 表示字符串前 `i` 个字符能够组成最少完全平方个数。显然,我们需要求解的是 `dp[n]`,其中 `n` 是字符串的长度。 我们从前往后遍历字符串,对于每个位置 `i`,我们需要枚举它之前的位置 `j`(注意,这里 `j` 不能等于 `i`),看看是否可以将 `s[j:i]` 构成一个完全平方。如果可以,那么我们就更新 `dp[i]`。具体来说,如果 `dp[j]` 不为 -1,那么我们可以用 `dp[j] + 1` 来更新 `dp[i]`。如果 `dp[i]` 还是 -1,那么我们赋值为 `dp[j] + 1`,否则我们将它和 `dp[j] + 1` 取一个较小值。 最终,我们输出 `dp[n]` 即可。如果 `dp[n]` 仍然为 -1,那么说明无法组成一个完全平方。 ### 回答2: 题目要求删除给定整的任意字,使结果保持为不带前导零的正整,并且最终的结果是一个完全平方。如果不能得到完全平方,则输出-1。 首先,我们可以判断一个是否为完全平方,可以从1开始逐个尝试,直到找到一个的平方等于给定的,或者找到一个大于给定的平方。如果找到了一个的平方等于给定,则返回该;如果找到一个大于给定的平方,则返回-1。 其次,我们需要找到给定整中有多少个数字需要删除,从而得到一个完全平方。我们可以采用动态规划的思想,定义一个组 dp,其中 dp[i] 表示使前 i 位字构成的整成为一个完全平方所需要删除的最少操作。则有以下状态转移方程: ``` dp[i] = min(dp[j]) + 1, j<i,其中 dp[j] 表示前 j 位字构成的整成为一个完全平方所需要删除的最少操作 ``` 最终的结果即为 dp[n]。 下面是使用 C 代码实现的示例: ```c #include <stdio.h> #include <math.h> int isPerfectSquare(int num) { int sqrt_num = sqrt(num); if (sqrt_num * sqrt_num == num) { return sqrt_num; } return -1; } int minOperations(int n) { int dp[n + 1]; dp[0] = 0; dp[1] = 1; for (int i = 2; i <= n; i++) { dp[i] = n; // 初始化为一个较大的 for (int j = 1; j < i; j++) { int sqrt_num = isPerfectSquare(i - j); if (sqrt_num != -1) { dp[i] = fmin(dp[i], dp[j] + 1); } } } return dp[n] == n ? -1 : dp[n]; } int main() { int n; printf("Please enter a positive integer: "); scanf("%d", &n); int result = minOperations(n); printf("Minimum number of operations: %d\n", result); return 0; } ``` 该程序首先判断是否能得到一个完全平方,如果能则输出最少操作,否则输出-1。 ### 回答3: 要求给定一个正整n,找出最少的操作,使得删除其中的几个数字后,所得到的正整一个完全平方。 首先,我们需要找到满足条件的完全平方。 我们可以用一个循环遍历从1开始的所有正整k,将k的平方存储在变量square中,当square小于等于n时,就记录下来。这样我们就得到了小于等于n的所有完全平方。 接下来,我们对这些完全平方进行判断。首先,统计n的位,即将n转换为字符串形式,并计算其长度。然后,将每个完全平方转换为字符串形式,计算其长度。 我们发现,删除字后的正整同样是一个完全平方,我们只需要判断两者的位是否相等即可。如果相等,则表示删除相同量的字后,原始正整会成为一个完全平方。 所以,我们对每个完全平方的位与n的位进行比较,如果相等,则记录删除字的最小量。最后返回最小量即可。 接下来是代码实现: ```c #include <stdio.h> #include <math.h> int minDeleteNum(int n) { int k = 1; int square; int minNum = -1; // 找到小于等于n的所有完全平方 while ((square = k*k) <= n) { // 转换为字符串并计算长度 int len1 = floor(log10(n)) + 1; int len2 = floor(log10(square)) + 1; // 判断是否相等,如果相等则记录删除字的最小量 if (len1 == len2) { int deleteNum = len1 - len2; if (minNum == -1 || deleteNum < minNum) { minNum = deleteNum; } } k++; } return minNum; } int main() { int n; printf("请输入一个正整n:"); scanf("%d", &n); int minNum = minDeleteNum(n); if (minNum == -1) { printf("不可能输出-1\n"); } else { printf("最少操作量为:%d\n", minNum); } return 0; } ``` 以上是一个用C语言实现的解法,通过遍历所有的完全平方,对比位来找到最少操作量。如果不可能得到一个完全平方,则输出-1。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值