牛牛以前在老师那里得到了一个正整数数对(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)