题解 | #数对#暴力搜索虽妙,但时间复杂度不让你贪
数对
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;
}