习题:Coprime Arrays(莫比乌斯反演&差分)

题目

传送门

思路

洛谷题意有点问题,建议直接翻译英文题面

对于数论,就应该暴力变形

\(b_i=\sum_{a_1=1}^{i}\sum_{a_2=1}^{i}\dots\sum_{a_k=1}^{i}[gcd(a_1,a_2\cdots,a_k)==1]\)

看到后面那一个gcd的部分,很容易就可以联想到\(\mu\)

\(b_i=\sum_{a_1=1}^{i}\sum_{a_2=1}^{i}\dots\sum_{a_k=1}^{i}\sum_{d|gcd(a_1,a_2\cdots,a_k)}\mu(d)\)

按照套路

\(b_i=\sum_{d=1}^{i}(\mu(d)*\lfloor\frac{i}{d}\rfloor^k)\)

之后套路性的整除分块

你就能再\(O(\sqrt n*log_n)\)的时间里单独处理出一个\(b_i\)

然后?

然后就超时了

这不废话?

我们思考怎么优化

首先肯定不能将^带进式子,不然会很麻烦

但是我们好像又必须要知道每一个\(b_i\)

我们考虑相邻两个的差异

\(b_i-b_{i-1}=\sum_{d=1}^{i}(\mu(d)*\lfloor\frac{i}{d}\rfloor^k)-\sum_{d=1}^{i-1}(\mu(d)*\lfloor\frac{i-1}{d}\rfloor^k)\)

然后我们惊奇的发现,再对于\(d\)确定的情况下

很多的式子都是可以相互抵消的,

所以我们只需要计算那些产生变化的点即可

很容易可以推出,只有当\(d|i\)时,前者会比后者大1

\(b_i-b_{i-1}=\sum_{d|i}(\mu(d)*(\lfloor\frac{i}{d}\rfloor^k-(\lfloor\frac{i}{d}\rfloor-1)^k)\)

之后?

将k次方记忆化之后

暴力就van事了

总时间复杂度\(O(n*logn*logn)\)

代码

#include<iostream>
using namespace std;
const long long mod=1e9+7;
int n,k;
int mu[2000005];
int pri[2000005];
int lenp;
bool vis[2000005];
long long b[2000005];
long long ans;
long long mem[2000005];
void oular()
{
    mu[1]=1;
    for(int i=2;i<=2000000;i++)
    {
        if(!vis[i])
        {
            pri[++lenp]=i;
            mu[i]=-1;
        }
        for(int j=1;pri[j]*i<=2000000&&j<=lenp;j++)
        {
            if(i%pri[j]==0)
            {
                mu[i*pri[j]]=0;
                vis[i*pri[j]]=1;
                break;
            }
            mu[i*pri[j]]=-mu[i];
            vis[i*pri[j]]=1;
        }
    }
}
long long qkpow(long long a,int b)
{
    if(b==n&&mem[a]!=0)
        return mem[a];
    if(b==0)
        return 1;
    if(b==1)
        return a;
    long long t=qkpow(a,b/2);
    t=t*t%mod;
    if(b%2==1)
        t=t*a%mod;
    if(b==n)
        mem[a]=t;
    return t;
}
int main()
{
    cin>>n>>k;
    oular();
    for(int i=1;i<=k;i++)
        for(int j=1;j*i<=k;j++)
            b[i*j]=(b[i*j]+(1ll*(mu[i]+mod)%mod)*(qkpow(j,n)-qkpow(j-1,n)+mod)%mod)%mod;
    for(int i=2;i<=k;i++)
    {
        b[i]=(b[i]+b[i-1])%mod;
        ans=(ans+(b[i]^i))%mod;
    }
    cout<<ans;
    return 0;
}
posted @ 2020-03-29 17:58  loney_s  阅读(166)  评论(0)    收藏  举报