Codeforces Round #701 (Div. 2) C. Floor and Mod
阿新 • • 發佈:2021-08-07
整除分塊
的求和式,使用整除分塊即可\(O(\sqrt n)\)處理
\[\sum\limits_{a=1}^x \sum\limits_{b=1}^y[\lfloor\frac{a}{b}\rfloor=a\%b ] \]題意:
法一:
將a改寫為kb+r,注意到\(k=\lfloor\dfrac{a}{b}\rfloor\),\(r=a\%b\),即k=r
所以a=k(b+1),且r<b,即k<b
所以每個k的貢獻區間為\(\dfrac{\min(x,b^2-1)}{b+1}\)
分兩段算,當\(b^2-1<=x\)時,答案是\(\sum(b-1)\),可以用等差數列求和直接做
當\(x<b^2-1\)時,這是形如\(\sum\lfloor\dfrac{x}{b+1}\rfloor\)
#include<bits/stdc++.h> #define int long long using namespace std; int rd(){ int ret=0, f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } void solve(){ int x,y; int ans=0; x=rd();y=rd(); int up=1; while(up*up-1<x&&up<=y) up++; ans+=(up-1)*(up-2)/2; for(int l=up+1,r;l<=y+1;l=r+1){ int v=x/l; if(v==0) break; r=min(y+1,x/v); ans+=v*(r-l+1); } printf("%lld\n",ans); } signed main(){ int T=rd(); while(T--) solve(); return 0; }
法2
注意到\(k\le \sqrt x\),採用列舉k的方式,我們求b的個數
剛剛的\(k(b+1)\le x\)可變形為\(b\le \dfrac{x}{k}-1\),同時還有\(b\le y\)
而\(k=r<b\),這是左邊界
因而每個k對答案的貢獻為\((k,\min(\dfrac{x}{k}-1,y)]\)
\(O(\sqrt x)\)列舉k,求和即可
未經許可,禁止搬運。#include<bits/stdc++.h> using namespace std; #define int long long int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0', c=getchar(); return ret*f; } int x,y; void solve(){ x=rd();y=rd(); int up=(int)(sqrt(x)+0.5),ans=0; for(int k=1;k<=up;k++) ans+=max(0ll,min(x/k-1,y)-k); cout<<ans<<endl; } signed main(){ int T=rd(); while(T--) solve(); return 0; }