hdu 6706 huntian oy(杜教筛)

题目链接:哆啦A梦传送门
题解:

f ( n , a , b ) = ∑ i = 1 n ∑ j = 1 i g c d ( i a − j a , i b − j b ) [ g c d ( i , j ) = = 1 ] 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] f(n,a,b)=i=1nj=1igcd(iaja,ibjb)[gcd(i,j)==1]
我们得知道有这个公式:
g c d ( i a − j a , i b − j b ) = i g c d ( a , b ) − j g c d ( a , b ) gcd(i^a-j^a,i^b-j^b)=i^{gcd(a,b)-j^{gcd(a,b)}} gcd(iaja,ibjb)=igcd(a,b)jgcd(a,b)

故上式等价于:
题目说了a,b互质,故a,b就不用管它了
f ( n , a , b ) = ∑ i = 1 n ∑ j = 1 i ( i − j ) [ g c d ( i , j ) = 1 ] = ( ∑ i = 1 n ∑ j = 1 i i − ∑ i = 1 n ∑ j = 1 i j ) [ g c d ( i , j ) = 1 ] = ∑ i = 1 n i ∗ φ ( i ) − ∑ i = 1 n ( i ∗ φ ( i ) 2 + [ i = = 1 ] ) = 1 2 { ( ∑ i = 1 n i ∗ φ ( i ) ) − 1 ) } \begin{aligned} f(n,a,b)&=\sum_{i=1}^{n}\sum_{j=1}^{i}(i-j)[gcd(i,j)=1]\\ &=(\sum_{i=1}^{n}\sum_{j=1}^{i}i-\sum_{i=1}^{n}\sum_{j=1}^{i}j)[gcd(i,j)=1]\\ &=\sum_{i=1}^{n}i*\varphi(i)-\sum_{i=1}^{n}(\frac{i*\varphi(i)}{2}+[i==1])\\ &=\frac{1}{2} \{(\sum_{i=1}^{n}i*\varphi(i))-1)\}\\ \end{aligned} f(n,a,b)=i=1nj=1i(ij)[gcd(i,j)=1]=(i=1nj=1iii=1nj=1ij)[gcd(i,j)=1]=i=1niφ(i)i=1n(2iφ(i)+[i==1])=21{(i=1niφ(i))1)}
减1是因为 g c d ( 1 , 1 ) = 1 gcd(1,1)=1 gcd(1,1)=1
故我们就可以杜教筛了。
f ( n ) = n ∗ φ ( n ) , g ( n ) = i d ( n ) = n f(n)=n*\varphi(n),g(n)=id(n)=n f(n)=nφ(n),g(n)=id(n)=n
由杜教筛的公式得:
S ( n ) = ∑ i = 1 n ∑ d ∣ i f ( d ) ∗ g ( i d ) − ∑ d = 2 n g ( d ) S ( ⌊ n d ⌋ ) = ∑ i = 1 n ∑ d ∣ i φ ( d ) ∗ i − ∑ d = 2 n d ∗ S ( ⌊ n d ⌋ ) = ∑ i = 1 n i 2 − ∑ d = 2 n d ∗ S ( ⌊ n d ⌋ ) \begin{aligned}S(n)&=\sum_{i=1}^{n}\sum_{d|i}f(d)*g(\frac{i}{d})-\sum_{d=2}^{n}g(d)S(\left \lfloor \frac{n}{d} \right \rfloor)\\ &=\sum_{i=1}^{n}\sum_{d|i}\varphi(d)*i-\sum_{d=2}^{n}d*S(\left \lfloor \frac{n}{d} \right \rfloor)\\ &=\sum_{i=1}^{n}i^2-\sum_{d=2}^{n}d*S(\left \lfloor \frac{n}{d} \right \rfloor)\end{aligned} S(n)=i=1ndif(d)g(di)d=2ng(d)S(dn)=i=1ndiφ(d)id=2ndS(dn)=i=1ni2d=2ndS(dn)

上面是用杜教筛写的。

赛时我自己用莫比乌斯反演推了一个公式,不知是哪里错,有点迷,下次遇到自己推出以为正确的公式,但就是出不来正确结果,而自己也不知道是哪里出问题时,应该果断放弃这个公式,转而去想其它方法解决。
赛时想的
代码:

#include<bits/stdc++.h>
#include<tr1/unordered_map>
const int N=1e6+10;
using namespace std;

typedef long long LL;

const LL mod=1e9+7;
const LL inv2=500000004;

const LL inv6=166666668;
const LL inv24=41666667;

bool vis[N];
int phi[N];
LL sum1[N];
int tot,prime[N];
tr1::unordered_map<int,LL>w;
void get(int maxn)
{
    tot=0;
    phi[1]=1;
    for(int i=2;i<=maxn;i++)
    {
        if(!vis[i])
        {
            prime[++tot]=i;///素数
            phi[i]=i-1; ///欧拉函数
        }
        for(int j=1;j<=tot&&prime[j]*i<=maxn;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }

    sum1[0]=0;
    for(int i=1;i<=maxn;i++){
            sum1[i]=(sum1[i-1]+1LL*i*phi[i]%mod)%mod;
    }

}

///前n项平方和
LL H(LL n)
{
    n%=mod;
    LL ans=n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
    return ans;
}
LL djs(int x)
{
    if(x<=1000000)return sum1[x];
    if(w[x])return w[x];
    LL ans=H((LL)x);
    for(int l=2,r;l<=x;l=r+1)
    {
        r=x/(x/l);
        ans=(ans-(1LL*(r-l+1)*(l+r)/2)%mod*djs(x/l)%mod+mod)%mod;
    }
    return w[x]=ans;
}


int main()
{
    int t,n;
    get(1000000);

    scanf("%d",&t);
    while(t--)
    {
        int a,b;
        scanf("%d%d%d",&n,&a,&b);
        int r;
        LL item=(djs(n)-1+mod)%mod;
        item=item*inv2%mod;

        printf("%lld\n",item);


    }
    return 0;
}


\begin{aligned}\end{aligned}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值