BZOJ1257: [CQOI2007]餘數之和
阿新 • • 發佈:2018-11-07
Description
給出正整數n和k,計算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值其中k mod i表示k除以i的餘數。 例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3 mod 5=0+1+0+3+3=7Input
輸入僅一行,包含兩個整數n, k。 1<=n ,k<=10^9Output
輸出僅一行,即j(n, k)。
Sample Input
Sample Output
7題解Here!
題目要求:$$Ans=\sum_{i=1}^n(k\%i)$$ 首先,我們要知道一個公式:$$a\%b=a-b\times\lfloor\frac{a}{b}\rfloor$$ 於是:$$Ans=\sum_{i=1}^n(k-i\times\lfloor\frac{k}{i}\rfloor)$$ $$\Rightarrow Ans=n\times k-\sum_{i=1}^n(i\times\lfloor\frac{k}{i}\rfloor)$$ 知道懵逼鎢絲反演的應該都會算後面那個——數論分塊。 複雜度$O(\sqrt n)$。 記得特判邊界。 附程式碼:#include<iostream> #include<algorithm> #include<cstdio> using namespace std; long long n,k,ans; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } void work(){ n=read();k=read(); ans=n*k; for(long long i=1,last=1;i<=n;i=last+1){ if(k/i!=0)last=min(k/(k/i),n); else last=n; ans-=1LL*(last-i+1)*(k/i)*(i+last)/2; } printf("%lld\n",ans); } int main(){ work(); return 0; }