P2260 [清华集训2012]模积和

传送门

显然式子可以变成:

然后发现两个部分差不多,就是余数求和,传送门

但是有限制 i ≠ j

所以特殊考虑 i=j 时的答案,减去就好了

当 i = j 时的答案

 

可以像余数求和那样吧 n mod i 变成 

然后展开一波可以得到:

= $n\times m\times min(n,m) - \sum _{i=1}^{min(n,m)}\times i\times n\times \left \lfloor \frac{m}{i} \right \rfloor - \sum _{i=1}^{min(n,m)}\times i\times m\times \left \lfloor \frac{n}{i} \right \rfloor + \sum _{i=1}^{min(n,m)}\times i^2\times \left \lfloor \frac{n}{i} \right \rfloor\times \left \lfloor \frac{m}{i} \right \rfloor$

然后可以像余数求和一样吧 $\left \lfloor \frac{n}{i} \right \rfloor$ 和 $\left \lfloor \frac{m}{i} \right \rfloor$ 相同的区间放在一起算

顺便说一下    怎么算

有一个公式:

      

注意:模数不是质数!

所以要先求出 6 的逆元

在代码里搞好麻烦啊,然后就另外打了一个暴力:

枚举所有 i 找到第一个 6i % 19940417 = 1 的值....

找到了就直接把 6 的逆元放到代码里当常数用..

提醒一下 [n/i] 不用逆元

然后就是代码了

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
const int crk=19940417;//%%%crk dalao
const int inv_6=3323403;//6在膜crk下的逆元2333
LL n,m,ans;
inline LL f1(LL l,LL r){ return (l+r)*(r-l+1)/2; }// 求∑ l+ l+1 + ... + r
inline LL f2(LL p){ return p*(p+1)%crk *(2*p+1)%crk *inv_6%crk; }// 求∑ 1^2 + 2^2 + ... + p^2
inline LL slove(LL x)//先求出不考虑i=j时的答案
{
    LL res=0; int j;
    for(int i=1;i<=x;i=j+1)
    {
        j=x/(x/i);
        res+=x/i*f1(i,j);
    }
    return res;
}
inline LL Slove(LL x,LL y)//减去i=j时的情况
{
    int j,l=min(x,y); LL res=n*m%crk*l%crk; 
    for(int i=1;i<=l;i=j+1)
    {
        j=min( x/(x/i) , y/(y/i) );
        res=(res+ (crk- (x/i)*f1(i,j) %crk *y%crk) ) %crk;
        res=(res+ (crk- (y/i)*f1(i,j) %crk *x%crk) ) %crk;
        res=(res+ (f2(j)-f2(i-1)+crk) %crk * (x/i)%crk * (y/i)%crk )%crk;
    }
    return res;
}
int main()
{
    cin>>n>>m;
    ans= ( (n*n-slove(n)) %crk)*( (m*m-slove(m)) %crk) %crk;
    ans= (ans-Slove(n,m)+crk) %crk;
    cout<<ans;
    return 0;
}

 

posted @ 2018-09-21 10:45  LLTYYC  阅读(198)  评论(0编辑  收藏  举报