习题: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;
}

浙公网安备 33010602011771号