【网易校招】数对--数学

题目描述
牛牛以前在老师那里得到了一个正整数数对(x, y), 牛牛忘记他们具体是多少了。
但是牛牛记得老师告诉过他x和y均不大于n, 并且x除以y的余数大于等于k。
牛牛希望你能帮他计算一共有多少个可能的数对。

输入描述:
输入包括两个正整数n,k(1 <= n <= 10^5, 0 <= k <= n - 1)。

输出描述:
对于每个测试用例, 输出一个正整数表示可能的数对数量。

输入

5 2

输出

7

说明
满足条件的数对有(2,3),(2,4),(2,5),(3,4),(3,5),(4,5),(5,3)

暴力嵌套两重循环,复杂度太高,105的数据范围肯定是过不去,找规律把前面的数比后面的数小的部分给先算出来,只循环后面数比前面数小的情况,试一试,时间也过不去,那只能从数学上找一找规律了;

首先说这个余数,假设这个数对是(x,y);那么要保证x%y >= k 那么必然 y要大于等于 k + 1 ;
下面对每一个确定的y,来看在1-n范围内的 x。在这个范围内开始取余数,当然 在范围足够大的情况下,余数肯定是有规律的循环出现的(1,2,3, … , y-1 ,0);
那么他会这么循环多少次呢?他会循环(n / y)次;每次循环有多少符合条件的呢?会有(y - k)个符合条件(因为要求的是 x % y >= k, 就是说余数等于k的是包含在内的,我们把0看作是每次余数循环的第一个,这样如果k是2,我们减去k就是减去了余数是0, 1这两个不符合条件的)
在这里插入图片描述
然后再看还可能会有不够一次循环的情况出现,那么不够一次循环,他剩下了多少个呢?剩下了(n % k)个,有多少个不符合条件的呢,有(k - 1)个,刚才是把0放到最上面计算了,但是现在没有那个0了,所以少了一个

代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

int main()
{
    int n, k;
    long long ans = 0;
    cin >> n >> k;
    if(k == 0){
        cout << 1LL * n * n << endl;
        return 0;
    }
    for(int i = k + 1; i <= n; i ++ )
    {
        ans += (n / i) * (i - k);
        if(n % i >= k)    ans += n % i - k + 1;
    }
    cout << ans << endl;
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值