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

来源:互联网 发布:配置windows update%0 编辑:程序博客网 时间:2024/05/16 15:30
                             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) {;}
代码

 

 
 
原创粉丝点击