题解 | #数对#
用数学方法来求解(画图辅助更加)(请看代码注释,一句话一句话理解) #include <stdio.h> int main() { long long int x, y, n, k, count = 0; scanf("%lld %lld", &n, &k); if (k == 0) { printf("%lld", n * n); } else { for (y = k + 1; y <= n; y++)//y小于等于k的所有情况,x%y的值都不会大于等于k,所以直接从y=k+1开始 { long long int ret = n % y >= k ? n % y - (k - 1) : 0;//因为取余是有循环的,结果不停的重复0到k-1,n%y是判断这一列中除了完整循环之外,是否会出现多余的一次不完整取余循环 //例如8%3(从1%3,2%3,直到8%3),取余结果有着两次完整循环{1,2,0},还留下了一次单独的{1,2},之所以要判断是否大于等于k,是想判断这次单独循环中是否会出现题目要求的 //x%y>=k,如果出现,除了计算完整循环内的满足条件的余数数之外,还要加上ret所赋值的单独循环中满足条件的余数数 //倘若满足条件,通过三目表达式给ret赋值n%y-(k-1),减去k-1是从剩余的余数数量中减去不满足条件的余数数量,就是满足条件的余数数量 //不满足条件,说明在单独循环中不会出现满足条件的数,直接给本次ret赋值0 count += (y - k) * (n / y) + ret;//y-k是计算一次循环中有几个余数满足数量,n/y计算有几次循环,加上ret就是本列的总count,依次计算count数就行 } printf("%lld", count); } return 0; }