BZOJ 2956 模积和

Posted on 2016-10-27 13:55  ziliuziliu  阅读(124)  评论(0编辑  收藏  举报

注意不要爆long long。朴素的分块。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 19940417
#define inv 3323403
using namespace std;
long long n,m,ans=0;
long long sum1(long long x)
{
    return (x*(x+1)/2)%mod;
}
long long sum2(long long x)
{
    return ((x*((x+1)*(2*x+1)%mod)%mod)*inv)%mod;
}
long long find1(long long x)
{
    long long l=1,r,ret=0;
    while (l<=x)
    {
        r=x/(x/l);
        ret=(ret+(r-l+1)*x%mod)%mod;
        ret=(ret-((sum1(r)-sum1(l-1)+mod)%mod*(x/l))%mod)%mod;ret=(ret+mod)%mod;
        l=r+1;
    }
    return ret%mod;
}
long long find2(long long x)
{
    long long l=1,r,ret=0;
    while (l<=x)
    {
        r=min(n/(n/l),m/(m/l));
        ret=(ret+((n*m)%mod*(r-l+1))%mod)%mod;
        ret=(ret-(m*(n/l))%mod*((sum1(r)-sum1(l-1)+mod)%mod)%mod+mod)%mod;
        ret=(ret-(n*(m/l))%mod*((sum1(r)-sum1(l-1)+mod)%mod)%mod+mod)%mod;
        ret=(ret+((n/l)*(m/l)%mod)*(sum2(r)-sum2(l-1)+mod)%mod)%mod;
        l=r+1;
    }
    return ret;
}
int main()
{
    scanf("%lld%lld",&n,&m);
    ans+=(find1(n)*find1(m))%mod;
    ans-=find2(min(n,m));ans=(ans+mod)%mod;
    printf("%lld\n",ans);
    return 0;
}