51nod-1225 餘數之和(分割槽間處理)
阿新 • • 發佈:2018-12-24
基準時間限制:1 秒 空間限制:131072 KB 分值: 80 難度:5級演算法題
F(n) = (n % 1) + (n % 2) + (n % 3) + ...... (n % n)。其中%表示Mod,也就是餘數。
例如F(6) = 6 % 1 + 6 % 2 + 6 % 3 + 6 % 4 + 6 % 5 + 6 % 6 = 0 + 0 + 0 + 2 + 1 + 0 = 3。
給出n,計算F(n), 由於結果很大,輸出Mod 1000000007的結果即可。
Input
輸入1個數N(2 <= N <= 10^12)。
Output
輸出F(n) Mod 1000000007的結果。
Input示例
6
Output示例
3
題解:
n有1e12這麼大,肯定不能暴力。
我們考慮將區間分成[1,sqrt(n)]和[sqrt(n),n]這兩個區間。
對於第一個區間,我們直接累加答案即可。
對於第二個區間我們發現,由於除數很大,其n/i在很大範圍內是一樣。
並且在n/i相同的這一區間內其貢獻滿足等差數列,到這裡問題就解決了。
#include<math.h> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define ll long long #define mod 1000000007 ll n,ans,last; ll inv=500000004;//2的逆元 int main(void) { scanf("%lld",&n); ll m=(ll)sqrt(n+0.5); for(ll i=1;i<=m;i++) ans=(ans+n%i)%mod; for(int i=1;i<=m;i++) { ll num=((n/i)%mod-n/(i+1)%mod+mod)%mod; ans=(ans+n%i*num%mod+(num*(num-1)%mod)%mod*inv%mod*i%mod)%mod; } if(n/m==m) ans=(ans-(n%m)+mod)%mod; printf("%lld\n",ans); return 0; }