2019校招真题——数对

题目

牛牛以前在老师那里得到了一个正整数数对(x, y), 牛牛忘记他们具体是多少了。

但是牛牛记得老师告诉过他x和y均不大于n, 并且x除以y的余数大于等于k。
牛牛希望你能帮他计算一共有多少个可能的数对。

输入描述:
输入包括两个正整数n,k(1 <= n <= 10^5, 0 <= k <= n - 1)。
输出描述:
对于每个测试用例, 输出一个正整数表示可能的数对数量。

解答

因为x除以y余数要大于等于k,所以y必须是[k-1,n]之间的整数。
为了更好地认识问题,用一个例子观察一下,比如此时x=11,y=4,k=3则

x=1,2,3,4 \quad 5,6,7,8 \quad 9,10,11

因为y=4,所以可以将数据4个一组,发现在每一组中余数的规律为1,2,3,0。因此可以确定每一组符合条件的x有y-k个,而n个数字中总共有n/y个,因此总共的符合条件的数对有(n%y)*(y-k)。
但是在n个数字中,最后一组数字往往不完整,所以需要特殊处理。最后一组数字的长度为n%k。剩下的数字中,前面的k-1(上例的9,10)个除以y余数都是小于k,因此剩下的数字中共有n%k-(k-1)个满足条件的。

分析完毕,代码如下:

#include<iostream>
#include <algorithm>
using namespace std;

int main(){
    long long n,k;
    cin>>n>>k;
    long long count = 0;
    long long zero = 0;
    if(k==0){
        count=n*n;
        cout<<count<<endl;
        return 0;
    }
    for(long long y = k+1; y <=n; y++){
        count+=(n/y)*(y-k);
        count+=max(zero,n%y-k+1);
    }
    cout<<count<<endl;
    return 0;
}

另外,算法核心是在for循环中,对于每一个符合的y,先算出n中以y为长度的每组数字中中符合的x。然后在最后一组数字中获得符合的x。但是如果当k==0时,在最后一组数字获得的x数量将会出错,因此当k==0时直接输出结果。
另外,在计算(n/y)*(y-k)时,由于n的取值最大为 1 0 5 10^5 105,如果用int来存储的话将会溢出。因此用long long来存储各项数据。

题目来源:https://www.nowcoder.com/practice/bac5a2372e204b2ab04cc437db76dc4f?tpId=98&tqId=32828&tPage=1&rp=1&ru=/ta/2019test&qru=/ta/2019test/question-ranking

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值