luogu2261 [CQOI2007]余數求和
阿新 • • 發佈:2018-03-04
除法 分塊 using 證明 end log n) CQ pre 。
除法分塊。
猜想: 記 \(g(x)=\lfloor k / \lfloor k / x\rfloor \rfloor\),則對於 \(i \in [x,g(x)]\),\(\lfloor k / i \rfloor\) 都相等。
證明: 顯然函數 \(y=k/x\) 單調遞減。顯然 \(\lfloor k/x \rfloor \leq k/x\)。則:
- \(g(x)=\lfloor k / \lfloor k / x\rfloor \rfloor \geq \lfloor k/(k/x) \rfloor=x \Rightarrow \lfloor k/g(x) \rfloor \leq \lfloor k/x \rfloor\)
- \(\lfloor k/g(x) \rfloor=\lfloor k/\lfloor k / \lfloor k / x\rfloor \rfloor \rfloor \geq \lfloor k/( k / \lfloor k / x\rfloor ) \rfloor=\lfloor k/x \rfloor\)。
於是 \(\lfloor k/g(x) \rfloor=\lfloor k/x \rfloor\)。則顯然對於 \(i \in [x,g(x)]\),\(\lfloor k / i \rfloor\) 都相等。我們還可以知道 \(\lfloor k/(g(x)+1) \rfloor < \lfloor k/g(x) \rfloor=\lfloor k/x \rfloor\)
回到問題,\(ans=\sum_{i=1}^n k \bmod i=nk-\sum_{i=1}^{\min(n,k)} \lfloor k/i \rfloor \times i\),當 \(\lfloor k/i \rfloor\) 相等時對 \(i\) 用等差數列求和就好了。
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, k, lst, end;
ll ans=0;
int main(){
cin>>n>>k;
for (int i=1; i<=min(k,n); i=end+1){
lst = k / i;
end = min(n, k / lst);
ans += (ll)lst * (end+i) * (end-i+1) / 2;
}
cout<<(ll)n*k-ans<<endl;
return 0;
}
luogu2261 [CQOI2007]余數求和