51Nod 1225 余数之和(除法分块+等差数列)
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的结果即可。
我们知道
F(n)=n%1+n%2+n%3+n%4.......+n%n
=n-(n/1*1)+n-(n/2*2)+n-(n/3*3)+n-(n/4*4) ........+n-(n/n*n) (ps:这里的除法都是整数除法)
=n*n-(n/1*1+n/2+2+n/3*3........+n/n*n)
由于 n/i 有 sqrt(n) 个不同的值
对与 n/i 相同 就构成了如下的等差序列
(n/i)*(i+(i+1)+(i+2)+(i+3)....+(i+m))
以上等式中的 n/i n/(i+1) n/(i+2) ....n/(i+m) 的值都相同 我们就可以使用等差数列求和公式
N*(A+B)/2 N为元素个数 A,B分别为数列的首项和最后一项
这个/2 相当于求在%意义下2的逆元
注意开longlong
注意取模 这个取模有毒!我在取模上WA了15次!!
1 #include <cctype> 2 #include <cstdio> 3 #include <iostream> 4 5 typedef long long LL; 6 7 const int mod=1000000007; 8 const int M=5e8+4; 9 10 LL n,ans; 11 12 int hh() { 13 std::cin>>n; 14 ans=n%mod*(n%mod)%mod; 15 for(LL t,r,i=1;i<=n;++i) { 16 t=n/i; 17 r=n/t; 18 ans=ans-((r-i+1)%mod*((r+i)%mod))%mod*M%mod*t%mod; 19 while(ans<0) ans+=mod; 20 i=r; 21 } 22 std::cout<<ans; 23 return 0; 24 } 25 26 int sb=hh(); 27 int main(int argc,char**argv) {;}
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现