51Nod 1225 余数之和(除法分块+等差数列)

                             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的结果即可。
 
Input
输入1个数N(2 <= N <= 10^12)。
Output
输出F(n) Mod 1000000007的结果。
Input示例
6
Output示例
3
 
我们知道 
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) {;}
代码

 

 
 
posted @ 2017-10-11 15:25  拿叉插猹哈  阅读(279)  评论(0编辑  收藏  举报