分块+数论分块 xjb乱改 xjb查询的
build(){
block=sqrt(n);//block表示每块的长度大小
num=n/block;if(n%block) num++; //num表示分块的个数 可能多出一点 所以+1
for(int i=1;i<=num;i++){
l[i]=(i-1)*block()+1,r[i]=i*block;
}
r[num]=n;
for(int i=1;i<=n;i++)
belong[i]=(i-1)/block+1;//belong 表示每个i 所存在的位置
}
int d[maxd]
数论分块 a[i]=n%i
i为1~n的数
结论:
1.对于一个块来说i为左端点
2.右端点为 r= n/(n/i) 所以下一块的左端点为n/(n/i)+1
3.n/i 代表有多少块 按i为左端点能分多少块
4.n/(n/i) 代表每块的长度 (左端点为i的这一块情况下)
广工 a题 https://ac.nowcoder.com/acm/contest/30896/A
取模
#include<iostream>
using namespace std;
int main()
{
int n, m; cin>> n >> m;
while(m--) {
int l, r; cin >> l >> r;
int ans = 0;
// [l, r]区间,找到其中分块的每一块左端点,维护最大值
for (int i = l; i <= r; i = n / (n / i) + 1) {
ans = max(ans, n % i);
}
cout << ans << endl;
}
}
上海理工大学 k题 取模https://ac.nowcoder.com/acm/contest/30532/K
#include"bits/stdc++.h"
using namespace std;
typedef long long ll;
const int mod=998244353;
const int inv2=(998244353+1)/2;
ll n;
int main(){
cin>>n;
ll ans=(n % mod)*(n % mod) %mod;
for(ll i=1,r;i<=n;i=r+1){
r=n/(n/i);//相同商的右端点
ans-=(n/i)%mod*((r+i)%mod)%mod*((r+1-i)%mod)%mod*inv2%mod;
ans=(ans%mod+mod)%mod;
}
cout<<ans<<'\n';
return 0;
}