例如 n = 20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
20 10 6 5 4 3 2 2 2 2 1 1 1 1 1 1 1 1 1 1
一个明显的规律,使得某个区间(区间长度可能为1)有连续的 数值相同,
把左右的区间块确定,那问题可以得到优化。
结论
已知 区间的左端点是L ,那么它的右端点是 
举例 : 建设 L = 7 时 , n/L = 20/7 = 2 , n/(n/L) = 20/2 = 10 符合区间 [ 7 , 10 ];
求区间内的和
int sum = 0;
for(int l=1,r; l<=n ; l=r+1){
r = n/(n/l);
sum += (r-l+1) * (n/l);
}
时间复杂 (
)
例题
题目:Problem - F - Codeforces
题目的意思就是 左边数字只能减,右边的数字只能加。
我们用数论分块能优化时间;
#include <bits/stdc++.h>
using namespace std;
int f(int n,int m,int x){
//((m-1)/x + 1 ) * x - m 这里求出x的倍数和m的最小差值 n-x 是求出 n变成x的次数
int ans = (((m-1)/x+1)*x-m) + (n-x);
return ans;
}
int main()
{
int t,n,m;
cin >> t;
while(t--){
cin >> n >> m;
if(n>=m){
cout << n-m << endl;
continue;
}
int ans = 1e9;
for(int l=1;l<=n;){
int x = (m-1)/l;
int r = (m-1)/x;
r = min(n,r);
ans = min(ans,f(n,m,l));
ans = min(ans,f(n,m,r));
l = r+1;
}
cout << ans << endl;
}
return 0;
}