洛谷P2260 [清华集训2012]模积和(BZOJ2956)

数学题

洛谷题目传送门
BZOJ题目传送门

推式子:

i=1nj=1m(n mod i)×(m mod j)(ij) ∑ i = 1 n ∑ j = 1 m ( n   m o d   i ) × ( m   m o d   j ) ( i ≠ j )

i=1n(n mod i)×j=1m(m mod j)i=1min(n,m)(n mod i)×(m mod i) ∑ i = 1 n ( n   m o d   i ) × ∑ j = 1 m ( m   m o d   j ) − ∑ i = 1 m i n ( n , m ) ( n   m o d   i ) × ( m   m o d   i )

i=1n(nini)j=1m(mjmj)i=1min(n,m)(nini)(mimi) ∑ i = 1 n ( n − i ⌊ n i ⌋ ) ∑ j = 1 m ( m − j ⌊ m j ⌋ ) − ∑ i = 1 m i n ( n , m ) ( n − i ⌊ n i ⌋ ) ( m − i ⌊ m i ⌋ )

i=1n(nini)j=1m(mjmj)i=1min(n,m)(nm+nimii2(mni+nmi)i) ∑ i = 1 n ( n − i ⌊ n i ⌋ ) ∑ j = 1 m ( m − j ⌊ m j ⌋ ) − ∑ i = 1 m i n ( n , m ) ( n m + ⌊ n i ⌋ ⌊ m i ⌋ i 2 − ( m ⌊ n i ⌋ + n ⌊ m i ⌋ ) i )

减号前面的直接像余数之和一样搞一搞,后面的除法分块算一下就好了。

有一个公式: ni=1i2=n(n+1)(2n+1)6 ∑ i = 1 n i 2 = n ( n + 1 ) ( 2 n + 1 ) 6

代码:

#include
#include
#include
#include
#define inv 3323403
#define MOD 19940417
#define F inline
using namespace std;
typedef long long LL;
LL n,m,ans,p1,p2,p3;
F LL ca(LL x,LL y){ return (y-x+1)*(x+y)/2%MOD; }
F LL cal(LL x){ return x*(x+1)%MOD*(x*2+1)%MOD*inv%MOD; }
F LL calc(LL x){
    LL ret=0;
    for (LL l=1,r;l<=x;l=r+1)
        r=x/(x/l),ret=(ret+x*(r-l+1)%MOD-ca(l,r)*(x/l))%MOD;
    return (ret+MOD)%MOD;
}
int main(){
    scanf("%lld%lld",&n,&m);
    ans=calc(n)*calc(m)%MOD;
    if (n>m) swap(n,m);
    for (LL l=1,r;l<=n;l=r+1){
        r=min(n/(n/l),m/(m/l));
        p1=n*m%MOD*(r-l+1)%MOD;
        p2=(n/l)*(m/l)%MOD;
        p2=p2*(cal(r)-cal(l-1)+MOD)%MOD;
        p3=(m*(n/l)+n*(m/l))%MOD*ca(l,r)%MOD;
        ans=(ans-(p1+p2-p3)%MOD+MOD)%MOD;
    }
    return printf("%lld\n",ans),0;
}

你可能感兴趣的:(洛谷,BZOJ,蒟蒻zxl的Blog专栏)