#P2359. 第1题-粮食
          
                        
                                    
                      
        
              - 
          
          
                      2000ms
            
          
                      Tried: 221
            Accepted: 73
            Difficulty: 3
            
          
          
          
                       所属公司 : 
                              华为
                                
            
                        
              时间 :2023年9月23日-国内
                              
                      
          
 
- 
                        算法标签>数学          
 
第1题-粮食
题面描述
塔子哥是某地区粮食公司的老板,最近从当地农场收购了 ( n ) 吨粮食。他需要将这些粮食公平地分配给不确定数量的分销商,采用除不尽向下取整的方法进行分配。输入一个整数 ( n ) 表示粮食吨数,输出不同粮食分配方案的总数。例如,若 ( n = 7 ),则可能的方案数为 ( 4 ),对应分销商数量为 ( 1, 2, 3, 7 ) 吨的分配。
思路:数学
- 
首先,我们知道,如果分销商的数量为i,那么每个分销商能得到的粮食数量就是n/i(向下取整)。因此,我们需要找到所有可能的i。
 - 
我们可以从1开始,逐渐增大i,直到i等于n/i。在这个过程中,每增加1,就意味着有一种新的分配方案。
 - 
当i等于n/i时,我们需要特殊处理。因为此时,i和n/i是相等的,所以只能算作一种分配方案,而不是两种。
 - 
最后,我们将所有的分配方案数加起来,就得到了答案。
 
代码分析
- 
输入与数据类型:
- 使用 
unsigned long long类型来存储输入的粮食吨数 ( n ),这是因为 ( n ) 的范围可以达到 ( 4294967295 ),需要足够大的数据类型以避免溢出。 
 - 使用 
 - 
平方根优化:
- 计算 n 的平方根,并将结果存储在 
sqrt(n)中。这是为了减少循环次数,只需要遍历到 sqrt(n)的值就可以找到所有可能的分销商数量。这样做的原因是,若i大于sqrt(n),那么n/i的值会小于sqrt(n),因此已经在之前的循环中处理过。 
 - 计算 n 的平方根,并将结果存储在 
 - 
方案计数逻辑:
- 使用一个 
for循环,从 ( 1 ) 开始遍历到sqrtn。 - 在每次迭代中,检查n/i 是否等于i:
- 如果不相等,则说明存在两种不同的分配方案i和n/i,因此 
ans加 2。 - 如果相等,说明此时的分销商数量和每个分销商获得的粮食数量相同,这种情况下只算作一种方案,
ans加 1。 
 - 如果不相等,则说明存在两种不同的分配方案i和n/i,因此 
 
 - 使用一个 
 - 
输出结果:
- 最后,输出累积的方案数 
ans。 
 - 最后,输出累积的方案数 
 
时间复杂度
O(n)
代码
C++
#include <iostream>
#include <cmath> // 引入cmath库以使用平方根函数
using namespace std;
typedef unsigned long long ull; // 定义一个无符号长整型别名
int main() {
    ull n; // 声明粮食的总吨数
    cin >> n; // 从标准输入读取粮食的总吨数
    ull ans = 0; // 初始化方案计数器
    ull sqrtn = sqrt(n); // 计算n的平方根,优化循环的上限
    // 遍历可能的分销商数量i
    for (ull i = 1; i <= sqrtn; i++) {
        if (n / i != i) { // 如果n // i和i不相等,说明有两种分配方案
            ans += 2; // 增加两种方案
        } else { // 如果n // i等于i
            ans += 1; // 只能算作一种方案
        }
    }
    cout << ans; // 输出最终的方案数
    return 0; // 程序正常结束
}
python代码
n = int(input())  # 从标准输入读取一个整数n,表示粮食的总吨数
i = 1  # 初始化分销商数量i,从1开始
# 当i小于n // i时,继续增加i的值
while i < n // i:
    i += 1  # 每次循环将i增加1,寻找合适的分销商数量
ans = i - 1  # 记录i减去1的值,这表示当i达到n // i之前的分销商数量
# 检查当i等于n // i时的特殊情况
if i == n // i:
    print(ans * 2 + 1)  # 如果相等,方案数为ans的两倍加一
else:
    print(ans * 2)  # 如果不相等,方案数为ans的两倍
Java代码
import java.util.*; // 导入Java的工具库
public class Main {
    static int min = Integer.MAX_VALUE; // 定义一个静态变量min,用于存储最小值(未使用)
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in); // 创建Scanner对象用于接收输入
        long n = sc.nextLong(); // 从输入中读取一个长整型数n,表示粮食的总吨数
        long res = 0; // 初始化结果变量res,用于计数不同的分配方案
        long i = 1; // 初始化分销商数量i,从1开始
        // 循环条件为i小于等于n/2
        while (i <= n / 2) {
            long num = n / i; // 计算每个分销商可以分到的粮食量
            long yu = n % i; // 计算n除以i的余数
            long s = yu / num; // 计算可增加的分销商数量(s)
            i = i + s + 1; // 更新i的值,增加分销商数量
            res++; // 计数,增加一个有效的分配方案
        }
        System.out.println(res + 1); // 输出最终结果,res加1是因为至少有一个分销商(i=1)
    }
}
        题目描述
小明是某地区粮食公司的老板。某天,小明的粮食公司从当地农场收购了 n 吨粮食。
然而,小明面临了一个复杂的任务:他需要将这些粮食平均分配给分销商,以便销售到全镇。但问题在于,分销商的数量是不确定的,他无法确定最终将有多少人参与销售。小明坚持采取公平的方式,所以他决定采用除不尽向下取整的方法来分配粮食。
请你帮小明求出分销商获得不同粮食数量的方案数。
输入格式
一行一个整数 n。
输出格式
一行一个整数,表示分销商获得粮食数的可能方案数。
7
4
【样例解释 #1】
分销商数量可能为:1,2,3,7;
分得粮食数量分别为:7,3,2,1。
说明
1≤n≤4294967295