[BZOJ 2956]模積和 分塊+數學

一開始忘記了平方數列求和,鬱悶:
sum[n]=n*(n+1)*(2*n+1)/6
其實打一個表是看得出規律的,但是要進行運算我們還是得把他變成數學公式纔可以啊:
對於取模運算:n%i=nnii
化簡以後就是喜聞樂見地 分塊了

#include<cstdio>
#include<iostream>
#include<cstring>
#define inv 3323403ll
#define Mod 19940417ll
#define maxn 100021
#define LL long long 
using namespace std;
LL n,m,s1,sm,s2,sn;
LL Q(LL a,LL b){return (b-a+1)*(b+a)/2%Mod;}
LL calc(LL x){return x*(x+1)%Mod*(2*x+1)%Mod*inv%Mod;}
int main(){
    scanf("%lld%lld",&n,&m);
    if(n>m)swap(n,m);
    for(LL num,i=1,j;i<=m;i=j+1){
        j=m/(m/i);num=j-i+1;
        sm=(sm+num*m%Mod-Q(i,j)*(m/i)%Mod+Mod)%Mod;
    }
    for(LL num,i=1,j;i<=n;i=j+1){
        j=n/(n/i);num=j-i+1;
        sn=(n*num%Mod-Q(i,j)*(n/i)%Mod%Mod+Mod)%Mod;
        s1=(s1+sn*sm%Mod)%Mod;
    }
    for(LL num,i=1,j;i<=n;i=j+1){
        j=min(n/(n/i),m/(m/i));num=j-i+1;
        s2=(s2+n*m%Mod*num%Mod-m*(n/i)%Mod*Q(i,j)+Mod)%Mod;
        s2=(s2-n*(m/i)%Mod*Q(i,j)%Mod+(n/i)*(m/i)%Mod*(calc(j)-calc(i-1))%Mod+2*Mod)%Mod;
    }
    printf("%lld",(s1-s2+Mod)%Mod);
    return 0;
}
發佈了339 篇原創文章 · 獲贊 18 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章