2019CCPC网络赛HDU6706--huntian oy(杜教筛+GCD性质+欧拉函数性质)

一.前置技能

GCD性质(Me的)

欧拉函数性质

狄利克雷卷积+杜教筛(也是Me的)

 

二.题意及分析

题目链接

题意

f(n,a,b)=\sum_{i=1}^n \sum_{j=1}^i gcd(i^a-j^a,i^b-j^b)[gcd(i,j)=1]\%(10^9+7)

 

推导:

这里直说关键结论,结论更详细推导推荐这篇博客

①由GCD性质

\large =\sum_{i=1}^n \sum_{j=1}^i (i^{gcd(a,b)}-j^{gcd(a,b)})[gcd(i,j)=1]\%(10^9+7)

②因为gcd=1,这道题a和b没作用了

2019CCPC网络赛HDU6706--huntian oy(杜教筛+GCD性质+欧拉函数性质)_第1张图片

③由欧拉函数性质(hdu3501),

左半部分有j与i互素约束,和为n*euler(n)

右半部分N>1,不大于N且和N互素的所有正整数的和为1/2*euler(n)*n  (这步当时不会证,gg)

右半部分还要注意加上N==1的情况

 

④经典杜教筛(还是最裸的),看这篇博客链接--应用三

\large \frac{1}{2}*\sum_{i=2}^{n}\varphi (i)*i-\frac{1}{2}

可以用狄利克雷卷积证明,最后得到

\large S(n)=\sum_{i=1}^{n}i^2-\sum_{d=2}^{n}d\cdot S(\lfloor\frac{n}{d}\rfloor)

杜教筛常规套路,前半部分平方和公式,n(n+1)(2n+1)/6,后半部分分块求

 

 

三.代码

存个取模版杜教筛

但数组空间看情况开,这里开1e7会MLE

#include
#include
#define N 1000010
using namespace std;
typedef long long ll;

templateinline void read(T &x)
{
    x=0;
    static int p;p=1;
    static char c;c=getchar();
    while(!isdigit(c)){if(c=='-')p=-1;c=getchar();}
    while(isdigit(c)) {x=(x<<1)+(x<<3)+(c-48);c=getchar();}
    x*=p;
}
const int mod=1e9+7;
int inv2,inv6;

bool vis[N];
int mu[N];
ll sum1[N],phi[N];
long long sum2[N];
int cnt,prim[N];
tr1::unordered_mapansphi;
tr1::unordered_mapansmu;
ll ksm(ll x, int y) {
    ll res = 1;
    while (y) {
        if (y & 1)
            res = res * x % mod;
        x = x * x % mod;
        y /= 2;
    }
    return res;
}

void get(int maxn)
{
    phi[1]=mu[1]=1;
    for(int i=2;i<=maxn;i++)
    {
        if(!vis[i])
        {
            prim[++cnt]=i;
            mu[i]=-1;phi[i]=i-1;
        }
        for(int j=1;j<=cnt&&prim[j]*i<=maxn;j++)
        {
            vis[i*prim[j]]=1;
            if(i%prim[j]==0)
            {
                phi[i*prim[j]]=phi[i]*prim[j]%mod;
                break;
            }
            else mu[i*prim[j]]=-mu[i],phi[i*prim[j]]=phi[i]*(prim[j]-1+mod)%mod;
        }
    }
    for(int i=1;i<=maxn;i++)sum1[i]=sum1[i-1]+mu[i],sum2[i]=(sum2[i-1]+i*phi[i]%mod)%mod;
}

long long djsphi(long long x)
{
    if(x<=1000000)return sum2[x];
    if(ansphi[x])return ansphi[x];
    long long ans=x%mod*(x+1)%mod*(2*x%mod+1)%mod*inv6%mod;
    for(long long l=2,r;l<=x;l=r+1)
    {
        r=x/(x/l);
        //cal(r)-cal(l-1)
        //ans-=(r-l+1)*(l+r)%mod*inv2%mod*djsphi(x/l)%mod;
        ans-=1ll*((1ll * (r + 1) * r / 2 - 1ll * l * (l - 1) / 2) % mod )*djsphi(x/l)%mod;
        ans=(ans+mod)%mod;

    }
    return ansphi[x]=ans;
}
int main()
{
    int t,n,a,b;
    read(t);
    get(1000000);
    inv2=ksm(2,mod-2);
    inv6=ksm(6,mod-2);
    
    while(t--)
    {
        read(n);
        read(a);
        read(b);
        printf("%lld\n",(djsphi(n)-1+mod)%mod*inv2%mod);
    }
    return 0;
}

 

你可能感兴趣的:(—————数论—————,莫比乌斯&欧拉,筛法)