暴力求解 之一 除法

本文介绍了一个利用枚举法解决特定数学问题的C++程序实例。该程序的目标是找出所有形如abcde/fghij=n的表达式,其中a~j为0~9数字的一个全排列,且n为给定的正整数。文章通过遍历可能的数值组合,并检查每一对数值是否满足题目条件来寻找答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

输入正整数n,按从小到大的顺序输出所有形如abcde/fghij=n的表达式,其中a~j恰好为数字0
~9 的一个排列,2<=n<=79

样例输入:

62

样例输出:

79546 / 01283 = 62

94736 / 05128 = 62

 

枚举 其实挺难得的   很难满足        不重样   想了一晚 怎么去构建 一个这个数 

不要想着去构建这个数,而是 去一批数中捞 一些数   ! 

想法是   从 1234 到 5000就行了   因为要 举出 很多  然后  判断 符合不 

这才够暴力,但是尽量考虑时间复杂度!!!!

#include"bits/stdc++.h"  // 通用头  PAT 牛客亲测能用
using namespace std; 
int main () 
{
	int i,j,n,s1,s2,flag[10];
    while(scanf("%d",&n))
    {
        for(i=1234;i<50000;i++)
        {
            memset(flag,0,sizeof(flag));
            /*flag保存每一位数字*/
            s1=i;
            s2=i*n;
            while(s1||s2)
            {
                if(!flag[s1%10])
                {
                    flag[s1%10]=1;
                    s1/=10;
                }
                else
                    break;
                if(!flag[s2%10])
                {
                    flag[s2%10]=1;
                    s2/=10;
                }
                else
                    break;
            }
            for(j=0;j<10;j++)
              if(!flag[j])
                  break;  /*判断是否是10个各不相同的数字*/
            if(j==10&&i*n<=98765) /*如果数字各不相同*/
            {
                if(i<10000) /*除数是一个四位数,有前导0*/
                  printf("%d / 0%d = %d\n",i*n,i,n);
                else
                  printf("%d / %d = %d\n",i*n,i,n);
            }
        }
    }
	
	
	
 } 

 

<think>嗯,用户让我介绍一下用分治法求解最大子数组问题的C语言代码。首先,我需要回忆一下分治法的基本思想。分治法是将问题分解成更小的子问题,分别解决后再合并结果。对于最大子数组问题,通常的解法有暴力法、动态规划和分治法。用户可能已经了解其他方法,现在想看看分治法的实现。 接下来,我需要确认最大子数组问题的分治法步骤。分治法处理这个问题时,通常将数组分成左右两部分,分别求左半部分、右半部分的最大子数组,然后处理跨越中间的情况。这三者的最大值就是整个数组的最大子数组和。这个思路对吗?是的,不过具体实现时需要注意递归的终止条件,以及如何高效计算跨越中间的情况。 然后,用户需要的是C语言代码。我需要确保代码结构清晰,函数分工明确。通常,分治法会有三个函数:一个主函数调用分治函数,分治函数处理递归,还有一个处理跨越中间的情况。比如,maxSubArray作为入口,调用divide函数,divide函数再递归处理左右部分,并调用crossSum处理中间情况。 接下来,处理跨越中间的子数组函数。这个函数需要从中间向左右扩展,分别计算左边和右边的最大和,然后合并。这一步容易出错,需要确保从mid开始向左,mid+1开始向右,然后相加得到跨越中间的最大和。这时候要注意数组越界的问题吗?比如当数组长度为0或1时,不过递归终止条件应该是当low == high时返回当前元素,避免越界。 然后,递归的终止条件是否正确?是的,当low等于high时,直接返回该元素,因为只有一个元素,最大子数组就是它自己。这一步没问题。 再考虑时间复杂度,分治法的时间复杂度是O(n log n),比动态规划的O(n)要差,但用户可能出于学习分治法的目的来询问。所以需要解释清楚这一点,说明分治法的优缺点。 接下来,编写代码示例。需要注意变量命名和结构。比如,divide函数接收数组、low、high参数,返回最大子数组和。crossSum函数计算中间部分的和。主函数中调用divide,并处理整个数组的范围。 测试用例方面,可能需要给出一个例子,比如用户提供的测试数组,并说明结果是否正确。比如数组{-2,1,-3,4,-1,2,1,-5,4},结果应该是6,对应子数组[4,-1,2,1]。这时需要确认代码是否能正确处理这种情况。 可能遇到的错误:在crossSum函数中,计算左右最大和时,循环条件是否正确?比如左半部分从mid开始向左遍历到low,右半部分从mid+1到high。初始化左右最大和为INT_MIN,然后逐步累加比较,这样可以正确找到左右的最大和。 另外,分治法在处理时是否考虑了所有可能的子数组?是的,因为左、右、跨中间三种情况覆盖了所有可能性,所以正确性是有保证的。 用户可能需要了解为什么分治法的时间复杂度是O(n log n)。每次递归分成两部分,合并时需要线性时间处理跨中间的情况,递归树的高度是log n,每层处理时间为O(n),所以总时间是O(n log n)。 最后,需要将代码用正确的格式展示,使用$$...$$包围代码块,并确保LaTeX语法正确。同时,用中文解释每一步的思路和代码结构,帮助用户理解分治法的应用。</think>分治法求解最大子数组问题的核心思路是:将数组分为左右两半,分别求解左右部分的最大子数组,再处理跨越中间的情况,最终取三者中的最大值。以下是分步解析和C语言代码实现: ### 分治法步骤分析 1. **分解**:将数组从中间分为左右两个子数组 2. **递归求解**: - 左半部分的最大子数组和 `leftMax` - 右半部分的最大子数组和 `rightMax` 3. **处理跨越中间的情况** `crossMax`: - 从中间向左找最大和 - 从中间向右找最大和 - 合并左右两边的最大和 4. **合并结果**:取 `max(leftMax, rightMax, crossMax)` ### C语言代码实现 ```c #include <stdio.h> #include <limits.h> // 计算跨越中间的最大子数组和 int crossSum(int arr[], int low, int mid, int high) { int sum = 0; int leftSum = INT_MIN; for (int i = mid; i >= low; i--) { sum += arr[i]; if (sum > leftSum) leftSum = sum; } sum = 0; int rightSum = INT_MIN; for (int j = mid + 1; j <= high; j++) { sum += arr[j]; if (sum > rightSum) rightSum = sum; } return leftSum + rightSum; } // 分治递归函数 int divide(int arr[], int low, int high) { if (low == high) return arr[low]; int mid = (low + high) / 2; int leftMax = divide(arr, low, mid); int rightMax = divide(arr, mid + 1, high); int crossMax = crossSum(arr, low, mid, high); int maxVal = (leftMax > rightMax) ? leftMax : rightMax; return (maxVal > crossMax) ? maxVal : crossMax; } // 主函数入口 int maxSubArray(int arr[], int n) { return divide(arr, 0, n - 1); } // 测试用例 int main() { int arr[] = {-2, 1, -3, 4, -1, 2, 1, -5, 4}; int n = sizeof(arr)/sizeof(arr[0]); printf("最大子数组和为:%d", maxSubArray(arr, n)); // 输出6 return 0; } ``` ### 代码解析 1. **crossSum函数**: - 从中间向左右两边扩展计算最大和 - 时间复杂度:$$ O(n) $$ 2. **divide函数**: - 递归终止条件:当子数组长度为1时直接返回元素值 - 递归计算左右子数组的最大和 - 合并三种情况的结果 3. **时间复杂度分析**: $$ T(n) = 2T(n/2) + O(n) $$ 根据主定理,时间复杂度为:$$ O(n \log n) $$ ### 关键点说明 1. **边界处理**:递归终止条件必须精确处理单个元素的情况 2. **中间值计算**:使用 `mid = (low + high)/2` 保证整数除法 3. **负数处理**:当数组全为负数时,算法会自动选择最大的单个元素 此实现完整展示了分治法的核心思想,适用于理解算法原理,但在实际工程中更推荐使用时间复杂度 $$ O(n) $$ 的动态规划方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值