k-th divisor_Codeforces

本文介绍了一个用于寻找整数因子的算法实现,通过遍历和条件判断来找出指定位置的因子。文章详细解释了如何处理特殊情况,并给出了完整的C语言代码示例。

Ok,声明下2017年2月10日23:27:51 这两天因为她和朋友,一直没有做题,也可能自己太懒散
这题让我记住的关键就是:转换说明符:%lld 丢了!然后便一错再错,错一次还要修一次电脑,开心的不得了
嗯,这款华硕笔记本,一直出网络故障(以至于打开网页一度失败),并且自己状态不佳,像个无头苍蝇 所以不得不苦笑承认,自己真是个Loser。

Ok,说下解题步骤 : 特别声明下:一个整数的因子个数有两种情况: 1). 比如 36 ,它有6 ,因子数:1 2 3 4 6 . 然后
4->9 3->12 2->18 1->36 ,而 6 是单独的,No : 2*t-1 2). 比如 12 , 因子数 : 1 2 3
. 然后 3->4 2->6 1-> 12 , No: 2*t 先行判断:如果是 前一半因子 ,直接 输出 结束 否则,就输出
前一半因子的相对一半(利用num数组保存,下标值应为:总和减去 K)

代码如下:

#include <stdio.h>
#define maxn 10000000
long long num[maxn]; 
int main(){
    long long n,k,i,t;
    scanf("%lld %lld",&n,&k);
    bool flag=0;
    for(t=0,i=1;i*i<=n;i++){
        if(n%i==0){
            if(i*i!=n)
                num[t]=n/i;
            else
                flag=1;
            t++;
            if(t==k){
                printf("%lld\n",i);
                return 0;
            }
        }
    }
    if(!flag&&k<=2*t)
        printf("%lld\n",num[2*t-k]);   
    else if(flag&&k<=2*t-1)
        printf("%lld\n",num[2*t-1-k]);  
    else
        printf("-1\n");         
    return 0;
}
<think>我们分析用户提供的代码片段: 用户希望在内核空间使用`div64_u64`函数,在用户空间直接使用除法运算符。 这种写法是可行的,但需要注意以下几点: 1. 在内核空间,`div64_u64`是Linux内核提供的64位除法函数,用于在32位架构上安全执行64位除法。 2. 在用户空间,对于64位数据类型,编译器会自动处理除法操作(对于64位系统,没有问题;对于32位系统,编译器会调用相应的运行时库函数,如`__aeabi_uldivmod`)。 但是,用户提供的代码片段存在一个潜在问题:没有考虑除数为0的情况。在除数为0时,内核空间和用户空间都会产生异常(内核可能会oops,用户空间可能会收到SIGFPE信号)。因此,建议添加除零检查。 改进后的代码: ```c if (msg_handler->execu_cnt == 0) { // 处理除数为0的情况,例如设置为0或一个默认值,或者报错 avr_time = 0; } else { #ifdef __KERNEL__ avr_time = div64_u64(msg_handler->sum_time_usec, msg_handler->execu_cnt); #else avr_time = msg_handler->sum_time_usec / msg_handler->execu_cnt; #endif } ``` 另外,需要注意: - 在内核代码中,`__KERNEL__`宏通常是由内核构建系统定义的,确保在内核编译时定义。 - 在用户空间程序中,我们不会定义`__KERNEL__`,因此会走`#else`分支。 因此,该代码片段在正确性上没有问题,但安全性上需要增加除零检查。 §§相关问题§§ 1. 在内核编程中,为什么不能直接使用除法运算符进行64位除法? 2. 在用户空间进行64位除法时,32位系统和64位系统有何区别? 3. 如何在内核模块中安全地处理除数为0的情况? 4. 除了除数为0,64位除法操作还可能遇到哪些边界情况需要处理? 5. 在内核空间,除了`div64_u64`,还有哪些常用的64位数学运算函数? </think> ### 条件编译方案评估与改进 您提供的方案基本可行,但存在一些潜在风险和改进空间: ```c #ifdef __KERNEL__ avr_time = div64_u64(msg_handler->sum_time_usec, msg_handler->execu_cnt); #else avr_time = msg_handler->sum_time_usec/msg_handler->execu_cnt; #endif ``` ### 方案优点 1. **简单直接**:清晰区分内核和用户空间 2. **编译通过**:两种环境下都能正常编译 3. **效率较高**:用户空间直接使用原生除法 ### 潜在问题与改进建议 #### 1. **除零保护缺失** ```c // 改进方案:添加除零检查 if (msg_handler->execu_cnt == 0) { avr_time = 0; // 或设置错误标志 } else { #ifdef __KERNEL__ avr_time = div64_u64(msg_handler->sum_time_usec, msg_handler->execu_cnt); #else avr_time = msg_handler->sum_time_usec / msg_handler->execu_cnt; #endif } ``` #### 2. **32位用户空间兼容性问题** 在32位系统上,直接除法可能产生`__aeabi_uldivmod`链接错误: ```c // 改进:用户空间统一使用兼容函数 #else // 自定义安全的用户空间除法 avr_time = user_div64_u64(msg_handler->sum_time_usec, msg_handler->execu_cnt); #endif ``` #### 3. **可维护性问题** 建议封装为统一函数: ```c static inline uint64_t safe_div64(uint64_t dividend, uint64_t divisor) { if (divisor == 0) return 0; #ifdef __KERNEL__ return div64_u64(dividend, divisor); #else return dividend / divisor; #endif } // 调用处 avr_time = safe_div64(msg_handler->sum_time_usec, msg_handler->execu_cnt); ``` ### 完整优化方案 ```c // 在公共头文件中 #ifndef COMMON_MATH_H #define COMMON_MATH_H #include <linux/types.h> // 通用类型定义 #ifdef __KERNEL__ #include <linux/math64.h> #else // 用户空间安全的64位除法 static inline uint64_t user_div64_u64(uint64_t dividend, uint64_t divisor) { return divisor ? dividend / divisor : 0; } #define div64_u64 user_div64_u64 #endif // 通用的除法包装函数 static inline uint64_t safe_div64(uint64_t dividend, uint64_t divisor) { return divisor ? div64_u64(dividend, divisor) : 0; } #endif // COMMON_MATH_H // 在业务代码中 #include "common_math.h" avr_time = safe_div64(msg_handler->sum_time_usec, msg_handler->execu_cnt); ``` ### 何时需要更复杂的方案 1. **32位用户空间支持** 当目标包括32位ARM/x86系统时,需实现完整的用户空间除法函数 2. **高性能要求** 使用内联汇编优化关键路径: ```c #else static inline uint64_t user_div64_u64(uint64_t n, uint64_t d) { uint64_t q; asm("divq %[d]" : "=a"(q) : "a"(n), [d]"r"(d)); return q; } #endif ``` 3. **跨平台兼容** 使用编译器内置函数: ```c #else #define div64_u64(n, d) __builtin_div64(n, d) #endif ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值