spoj GCDMAT

来源:互联网 发布:网络口语培训班 编辑:程序博客网 时间:2024/06/18 08:27

题目大意:给定 a,b,c,d,求 bi=adj=cgcd(i,j)

i=1nj=1mgcd(i,j)=d=1ndi=1ndj=1md[gcd(i,j)==1]=d=1ndi=1ndj=1mdg|i,jμ(g)=d=1ndg=1ndμ(g)ngdmgd

然后就随便搞了嘛QAQ
大水怪,嘿嘿嘿

#include<iostream>#include<algorithm>#include<cstdlib>#include<cstdio>#include<ctime>#include<cmath>#include<cstring>#include<string>#define LL long long#define N 50002#define M 1000000007using namespace std;int tot,T,n,m,a,b,c,d;int miu[N],prime[N],v[N];void get_prime(){    miu[1]=1;    for (int i=2;i<N;i++)    {        if (!v[i]) miu[prime[tot++]=i]=-1;        for (int j=0;j<tot&&i*prime[j]<N;j++)        {            v[i*prime[j]]=true;            if (i%prime[j]==0) break;            miu[i*prime[j]]=-miu[i];        }    }    for (int i=2;i<N;i++) (miu[i]+=miu[i-1])%=M;}LL sum(int n,int m){    LL ret=0;    for (int i=1,j;i<=n;i=j+1)    {        j=min(m/(m/i),n/(n/i));        (ret+=(LL)(miu[j]-miu[i-1])*(n/i)*(m/i))%=M;    }    return ret;}LL cal(int n,int m){    if (!n||!m) return 0;    LL ret=0;    if (n>m) swap(n,m);    for (int i=1,j;i<=n;i=j+1)    {        j=min(m/(m/i),n/(n/i));        (ret+=(LL)(j-i+1)*(i+j)/2%M*sum(n/i,m/i))%=M;    }    return ret;}int main(){    scanf("%d",&T);    scanf("%d%d",&n,&m);    get_prime();    while (T--)    {        scanf("%d%d%d%d",&a,&b,&c,&d);        cout<<(cal(c,d)+cal(a-1,b-1)-cal(c,b-1)-cal(a-1,d)+M+M)%M<<endl;    }    return 0;}
0 0
原创粉丝点击