题解 | #数对#暴力搜索虽妙,但时间复杂度不让你贪

数对

http://www.nowcoder.com/practice/bac5a2372e204b2ab04cc437db76dc4f

用普通的遍历是没办法走到最后的,数据一但非常大时,时间复杂度就会报错,这里就需要推导一下数学公式:(n / y) * (y - k) + ((n % y < k) ? 0, (n % y - k + 1));

当 y <=k 时,意味着任何数字取模y的结果都在 [0, k-1]之间,都是不符合条件的。

当 y = k+1=4 时,x符合条件的数字有 3,7

当 y = k+2=5 时,x符合条件的数字有 3,4,8,9

当 y = k+3=6 时,x符合条件的数字有 3,4,5,9,10

当 y = k+n时,

x小于y当前值,且符合条件的数字数量是:y-k个,

x大于y当前值,小于2*y的数据中,且符合条件的数字数量是:y-k个

从上一步能看出来,在y的整数倍区间内,x符合条件的数量就是 (n / y) * (y - k)个

n / y 表示有多少个完整的 0 ~ y区间, y - k 表示有每个区间内有多少个符合条件的数字

最后还要考虑的是6...往后这种超出倍数区间超过n的部分的统计

n % y 就是多出完整区间部分的数字个数,其中k以下的不用考虑,则符合条件的是 n % y - (k-1) 个 这里需要注意的是类似于9这种超出完整区间的数字个数 本就小于k的情况,则为0

int main()
{
    long n,k = 0;
    long count =0;
    while(~scanf("%ld %ld",&n,&k))
    {
    if(k==0)
    {
        printf("%ld\n",n*n);
        continue;
    }
        for(long j = k+1;j<=n;j++)
        {
                long help = n%j<k?0:(n%j)-k+1;
                count+=(j-k)*(n/j)+help;
        }
    printf("%ld\n",count);
    }
    return 0;
}
全部评论
这里的证明是假设 n和k为 10 和 3铁子们
2 回复 分享
发布于 2022-02-17 17:41
妙啊
点赞 回复 分享
发布于 02-06 17:17 湖北

相关推荐

程序员猪皮:看不到八股什么意思
点赞 评论 收藏
分享
评论
13
2
分享
牛客网
牛客企业服务