【2011集训队出题】Crash的数字表格

来源:互联网 发布:淘宝商品排名软件 编辑:程序博客网 时间:2024/05/16 00:28

Description


i=1nj=1mlcm(i,j)mod20101009

Solution

对于一个式子的做法思路,有思路以后应该注意的东西

对于一个式子必须化简

i=1nj=1mij1gcd(i,j)mod20101009

对于有gcd的题目,常见思路

我们设n< m
我们可以枚举最小公倍数d
我们设一个

f(d)=i=1nj=1mij(gcd(i,j)=d)

所以答案是
ans=d=1n1df(d)

那么f(d)的求解自然就可以想到莫比乌斯反演
g(d)=d=1ndf(d)

莫比乌斯反演后
f(d)=i=1ndg(id)μ(i)

g(d)其实可以化简
那么g(d)就是等于
(d+2d+3d+......+nd)(d+2d+3d+......+md)

因为这些都是d的倍数,然后在矩阵中再两两相乘。
提取供应式d,然后在用等差数列求和,得到
d2nd(nd+1)md(md+1)

把这个带入答案求解里面
ans=d=1n1di=1ndd2i2ndi(ndi+1)mdi(mdi+1)μ(i)

然后发现可以消掉一个d
ans=d=1ni=1ndi2dndi(ndi+1)mdi(mdi+1)μ(i)

分块大法

有整除的式子题,就用分块大法

预处理

用一个前缀和预处理mu(i)i2

注意会爆空间

坑死人

Code

#include<iostream>#include<algorithm>#include<cmath>#include<cstring>#include<cstdio>#define fo(i,a,b) for(i=a;i<=b;i++)#define ll long longconst int mo=20101009;const int maxn=10000005;using namespace std;ll i,j,k,l,t,n,m,r,l1,r1,o,q;ll sum,sum1,ni,ans2,ans;int qian[maxn];int miu[maxn],zhi[maxn];bool bz[maxn];ll chu2(ll x){    if(x%2==0)return x/2*(x+1)%mo;    else return (x+1)/2*x%mo;}int main(){    scanf("%d%d",&n,&m);    if(n>m)swap(n,m);    miu[1]=1;qian[1]=1;    fo(i,2,n){        if(!bz[i]){            zhi[++zhi[0]]=i;            miu[i]=-1;        }        fo(j,1,zhi[0]){            t=zhi[j]*i;            if(t>n)break;            bz[t]=1;            if(i%zhi[j]==0)break;            miu[t]=-miu[i];        }        qian[i]=(qian[i-1]+miu[i]*i%mo*i%mo)%mo;    }    l1=1;    while(l1<=n){        r1=min(n / (n / l1),m / (m / l1));        t=n / l1;        k=m / l1;        l=1;        ans2=0;        while(l<=t){            r=min(t/(t/l),k/(k/l));o=t/l,q=k/l;            ans2=(ans2+(qian[r]-qian[l-1]+mo)*chu2(o)%mo*chu2(q))%mo;                l=r+1;        }        ans=(ans+(chu2(r1)-chu2(l1-1)+mo)%mo*ans2%mo)%mo;        l1=r1+1;    }    printf("%lld\n",ans);}
1 0
原创粉丝点击