牛牛以前在老师那里得到了一个正整数数对(x, y), 牛牛忘记他们具体是多少了。
但是牛牛记得老师告诉过他x和y均不大于n, 并且x除以y的余数大于等于k。
牛牛希望你能帮他计算一共有多少个可能的数对。
牛牛以前在老师那里得到了一个正整数数对(x, y), 牛牛忘记他们具体是多少了。
牛牛希望你能帮他计算一共有多少个可能的数对。
输入包括两个正整数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)
// 时间复杂度O(N)
// 将除数y从k+1 开始计算,除数为y时,数对的个数包括两部分: n/y*(y-k) 和多出来的另一部分,这部分需要看
// n%y 和k的大小关系
import java.util.*;
public class Main{
public static void main(String[] arsg){
Scanner sc= new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
long sum = 0;
int t = 0;
int tt = 0;
for(int i=k+1;i<=n;i++){
t++;
tt = (n%i - k + 1) >0 ? (n%i - k + 1):0;
sum+=n/i*t+tt;
}
if(k == 0) sum-=n;// k=0 特殊情况 多计算了n次
System.out.print(sum);
}
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
Long count=0l;
long n=scanner.nextInt();
long k=scanner.nextInt();
/*暴力解决时间复杂度过高
* for(int y=k;y<=n;y++){
for(int x=k;x<=n;x++){
if(x%y>=k)
count++;
}
}*/
if(k==0){
count=n*n;
}else{
//余数要大于k,除数一定是从k+1开始的。
for(long y=k+1;y<=n;y++){
//余数是从0到y-1循环的,
//对于每个y值,x从1到n包含n/y个余数循环,
//每个余数循环中只有y-k个符合条件的。
count+=(n/y)*(y-k);
//剩下一个不完整的余数循环,判断这部分最大的余数是否大于k
if(n%y>=k)
count+=n%y-k+1;
}
}
System.out.println(count);
}
}
"""
对于(x,y),x和y均不大于n, 并且x除以y的余数大于等于k
y从k+1到n遍历:
x的个数 = (n // y) * (y - k) + max((n % y) - k + 1, 0)
求和即所得
by the way:考虑特例 k=0时,y应从2开始遍历
测试用例中 0%1 计算在内
其他解答中 k=0时,直接输出n*n是没有依据的
"""
import sys
if __name__ == "__main__":
# sys.stdin = open('input.txt', 'r')
n, k = list(map(int, input().strip().split()))
ans = 0
for y in range(max(2,k + 1), n + 1):
ans += (n // y) * (y - k) + max((n % y) - k + 1, 0)
if k==0:
ans += 1 #测试用例中 0%1 计算在内
print(ans)
n,k = map(int,input().split()) i = 1 count = 0 if k == 0: print(n*n) else: while k+i <= n: a = (n//(k+i))*i b = n%(k+i) if b < k: count+=a if b>=k: count+=(a+b-k+1) i+=1 print(count)
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,k;
long long ans = 0,cnt,res;
scanf("%d %d",&n,&k);
for(int i=k+1;i<=n;i++){
cnt = n/i; ///前面划分了cnt段长度为i的区间
ans += cnt*(i-k); ///每段贡献i-k
if(n%i==0)continue;
res = n-cnt*i; ///最后一段长度
if(k==0)ans += res; ///k=0时特殊处理最后一段
else if(res>0&&res>=k)ans += res-k+1; ///当最后一段长度>=k时,贡献的答案
}
printf("%lld\n",ans);
return 0;
}
#coding:utf-8 import sys line=sys.stdin.readline().split() n=int(line[0]) k=int(line[1]) count=0 if k==0: count=n*n else: for y in range(k+1,n+1): count+=n/y*(y-k)+max(0,n%y-k+1) print count
importjava.util.Scanner;publicclassMain {publicstaticvoidmain(String[] args) {Scanner sc = newScanner(System.in);while(sc.hasNext()) {intn = sc.nextInt();intk = sc.nextInt();longnlong = (long)n;longklong = (long)k;longtimes = nlong - klong;if(klong == 0L){times = times - 1L;}longallNum = (times * (times + 1)) / 2;for(longy = klong + 1L; y <= nlong; y++){allNum += (nlong / y - 1L) * (y - klong);longremine = (nlong % y) - klong + 1L;if(remine >= 0L){allNum += remine;}}System.out.println(allNum);}sc.close();}}
// 时间复杂度O(N)
// y =>[k+1,n] res=n/y*(y-k)
// n%i-k>=0 ? res+n%i-k+1:res
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
})
let res = 0
rl.on('line',line =>{
let n = +line.split(' ')[0],
k = +line.split(' ')[1]
if(k === 0){
res = n*n
console.log(res)
return
}
//x=[1,n] y=[k,n] 遍历y,满足条件x的总数为(n/y)*(y-k)
for (let i = k+1; i <= n; i++) {
let cnt = Math.floor(n/i)
let restLen = n%i
res += cnt * (i-k)
restLen >=k ? res += restLen-k+1: res
}
console.log(res)
}) #include <cstdio>
#define ll long long
int main(){
int n,k;
scanf("%d%d",&n,&k);
ll res = 0;
//x=p*y+r,r>=k
//因为除数>余数,即y>r,所以y>k
//枚举y,因为1<=x<=n,当给定y时,我们先求出最大的p:pMax
//那么当p取[0,pMax-1]时,r能取到[k,y-1]的所有值
//当p取pMax时,需要看当前余数r比k大的数量(r-k+1)
for(int y=k+1;y<=n;y++){
//pMax>=1
int pMax = n/y;
int r = n - pMax*y;
//当p取到[0,pMax-1]时,r可以取[k,y-1],共pMax*(y-k)个
res+=(ll)pMax*(y-k);
//注意,当p=0时,x=r>=k,若k==0,那么x可以取到0,这不符合题目中x为正整数的要求,需要去掉
if(!k) res--;
//当p=pMax时,只能取[k,r]共(r-k+1)个数
if(r>=k) res+=(r-k)+1;
}
printf("%lld\n",res);
return 0;
}
#include <cstdio>
#define ll long long
int main(){
int n,k;
scanf("%d%d",&n,&k);
if(k==0) printf("%lld\n",(ll)n*n);
else{
ll res = 0;
for(int y=k+1;y<=n;y++){
int pMax = n/y;
int r = n - pMax*y;
res+=(ll)pMax*(y-k);
if(r>=k) res+=(r-k)+1;
}
printf("%lld\n",res);
}
return 0;
} import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
long n = input.nextInt();
long k = input.nextInt();
long count = 0;
if (k==0)
System.out.println(n*n);
else {
for (long i = k+1;i<=n;i++){
//+号前是分成一个一个小间隔,将每个小间隔里满足条件的个数乘以小间隔个数。
//+号后求的是最后一个小间隔里面是否有满足条件的。
count += (n/i)*(i-k) + Math.max(0,n%i-k+1);
}
System.out.println(count);
}
}
}
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,k;
long long ans = 0;
scanf("%d%d",&n,&k);
if(k==0) ans = 1LL*n*n;
else{
for(int y=1;y<=n;y++){
if(k>=y) continue;
ans += y-k;
for(int j=1;;j++){
if(y*j+k>n) break;
int l = y*j+k;
int r = min(y*(j+1)-1,n);
ans += r - l+1;
}
}
}
printf("%lld\n",ans);
return 0;
}
/*
要用long。
*/
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
long n = in.nextInt();
long k = in.nextInt();
long ans = 0;
long cir = 0; //出现的循环数
long lef = 0; //出现的余数
long cnt = 0; //每次循环出现的数对个数
if (k == 0) {
ans = n * n;
} else {
for (long i = k + 1; i <= n; i++) {
cir = n / i;
lef = n % i;
cnt = i - k;
ans += cir * cnt;
if (lef >= k)
ans += lef - k + 1;
}
}
System.out.println(ans);
}
}
/**
*运行时间:37ms
*思路就是对暴力方法做优化
*1. 要满足y <= n,并且x % y >= k,就要保证y的范围在[k + 1, n],构成第1层循环
*2. 同样x <= n,并且x % y >= k,就要保证y的范围在[k, n],构成第2层循环
* 不过第2层的优化在于只有每一层循环只有y-k个数对满足条件
*
*/
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(), k = in.nextInt();
if(k == 0) {
System.out.println((long) n * n);
return;
}
long sum = 0;
for (int y = k + 1; y <= n; ++y){
int d = y - k;
for (int x = k; x <= n; x += y){
sum += Math.min(n - x + 1, d);
}
}
System.out.println(sum);
}
}
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
long long n,k;
cin>>n>>k;
long long ans=0;
for(int y=max(1LL,k);y<=n;++y)
{
int res=0;
res=n/y*(y-k);
if(n%y>=k)
if(k)
res+=n%y-k+1;
else res+=n%y;
ans+=res;
}
cout<<ans<<endl;
} #include<stdio.h>
#define max(x,y) ((x)>(y)?(x):(y))
int main() {
int n, k; while (~scanf("%d%d", &n, &k)) { int y; long long count = 0; for (y = k + 1; y <= n; ++y) { count += (n / y)*(y - k) + max(n%y+1-k, 0); if (!k) count--; } printf("%lld\n", count); } return 0;
}
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long n = sc.nextInt();
long k = sc.nextInt();
long ans = 0L;
if (k == 0) {
ans = n * n; // 任何两对数的余数都是大于等于零
} else {
for (long y = k + 1; y <= n; y++) {
ans += (n / y) * (y - k) + Math.max(0, n % y - k + 1);
// 假设n=10,k=3,则对y来说只能是4,5,6,7,8,9,10
// 当y=4,(n/y)*(y-k)代表x小于等于8(8是4的整数倍)时有(3,4),(7,4),Math.max(0,n%y-k+1)代表x大于8时符合题意的对数为0
// 当y=5,(n/y)*(y-k)代表x小于等于10(10是5的整数倍)时有(3,5),(4,5),(8,5),(9,5),Math.max(0,n%y-k+1)代表x大于10时符合题意的对数为0
// 当y=6,(n/y)*(y-k)代表x小于等于6时有(3,6),(4,6),(5,6),Math.max(0,n%y-k+1)代表x大于6时符合题意的对数为2,分别是(9,6),(10,6)
// 当y=7,(n/y)*(y-k)代表x小于等于7时有(3,7),(4,7),(5,7),(6,7),Math.max(0,n%y-k+1)代表x大于7时符合题意的对数为1,是(10,7)
// ...以此类推
}
}
System.out.println(ans);
}
}
| 余数 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ... |
| 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | ... |
| 2 | 0 | 0 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | ... |
| 3 | 0 | 1 | 0 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | ... |
| 4 | 0 | 0 | 1 | 0 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | ... |
| 5 | 0 | 1 | 2 | 1 | 0 | 5 | 5 | 5 | 5 | 5 | 5 | 5 | ... |
| 6 | 0 | 0 | 0 | 2 | 1 | 0 | 6 | 6 | 6 | 6 | 6 | 6 | ... |
| 7 | 0 | 1 | 1 | 3 | 2 | 1 | 0 | 7 | 7 | 7 | 7 | 7 | ... |
| 8 | 0 | 0 | 2 | 0 | 3 | 2 | 1 | 0 | 8 | 8 | 8 | 8 | ... |
| 9 | 0 | 1 | 0 | 1 | 4 | 3 | 2 | 1 | 0 | 9 | 9 | 9 | ... |
| 10 | 0 | 0 | 1 | 2 | 0 | 4 | 3 | 2 | 1 | 0 | 10 | 10 | ... |
| 11 | 0 | 1 | 2 | 3 | 1 | 5 | 4 | 3 | 2 | 1 | 0 | 11 | ... |
| 12 | 0 | 0 | 0 | 0 | 2 | 0 | 5 | 4 | 3 | 2 | 1 | 0 | ... |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
temp = list(map(int, input().split())) n = temp[0] k = temp[1] if k == 0: ans = n * n # k=0是比较特殊的 else: ans = 0 for y in range(k + 1, n + 1): # 从每一列来看,根据每y个一个循环的规律,快速计算余数矩阵余数值 # cycle = [i for i in range(1, y)] + [0] # 循环部分 satisfy_num = y - k # 一个循环中满足的组合个数 cycle_num = n // y # 完整循环个数 res_num = n % y # 剩余不完整部分循环中的元素个数 ans += satisfy_num * cycle_num + max(res_num - k + 1, 0) # 注意这里最差就是不完整部分满足个数为0,但是不能为负数 print(ans)