题解:CF915G Coprime Arrays

题意

我们称一个大小为 n 的数组 a 互质,当且仅当 gcd(a1,a2,,an)=1

给定 n,k,对于每个 i (1ik),你都需要确定这样的数组的个数——长度为 n 的互质数组 a ,满足对每个 j (1jn),都有 1aji

分析

我们设 f(x)x 所对应的互质数组的个数。

按照题意,可以列出这样一个式子:

f(x)=a1=1xa2=1xan=1x[gcdi=1nai=1]

简单推一下式子:

f(x)=a1=1xa2=1xan=1x[gcdi=1nai=1]=a1=1xa2=1xan=1xε(gcdi=1nai)

因为 μ1=ε,即 ε(x)=d|xμ(d) 所以有:

f(x)=a1=1xa2=1xan=1xd|gcdi=1naiμ(d)=a1=1xa2=1xan=1xd|a1,,d|anμ(d)

变换求值顺序,枚举 d

f(x)=d=1xμ(d)a1=1xda2=1xdan=1xd1=d=1xμ(d)xdn

于是我们得到了一个 O(kk+klogn) 的做法。

n,k2×106 的规模下,无法通过本题。


有个显然的引理:

d|xxd=x1d+1

据此考虑差分:

Δf(x)=f(x)f(x1)=d=1xμ(d)xdnd=1x1μ(d)x1dn=d=1xμ(d)(xdnx1dn)

根据上述引理,当且仅当 d|x(xdnx1dn)0,所以上式可以如下改写:

Δf(x)=d|xμ(d)(xdnx1dn)

所以,我们可以枚举 d,然后将所有满足 d|xΔf(x) 加上 μ(d)(xdnx1dn)

通过前缀和统计答案。

时间复杂度 O(klogn+klogk)

Code

#include<bits/stdc++.h>
using namespace std;
#define maxn 2000006
#define mod 1000000007
int mu[maxn];
bool vis[maxn];
vector<int> pri;
void init()
{
mu[1]=1;
for(int i=2;i<maxn;i++)
{
if(!vis[i]) mu[i]=-1, vis[i]=1, pri.emplace_back(i);
for(auto p:pri)
{
if(p*i>=maxn) break;
vis[p*i]=1;
if(i%p==0) break;
mu[i*p]=-mu[i];
}
}
}
int ksm(int64_t x, int l)
{
int64_t ret=1;
for(;l;l>>=1, x=x*x%mod)
if(l&1) ret=ret*x%mod;
return ret;
}
int lev[maxn], det[maxn];
int main()
{
int n, k;
cin>>n>>k;
init();
for(int i=1;i<=k;i++)
lev[i]=ksm(i, n);
for(int d=1;d<=k;d++)
for(int j=1;d*j<=k;j++)
det[d*j]=((det[d*j]+mu[d]*(mod+(lev[j]-lev[j-1])%mod)%mod)%mod+mod)%mod;
int ans=0, otp=0;
for(int i=1;i<=k;i++)
otp=(otp+(i^(ans=(ans+det[i])%mod)))%mod;
cout<<otp%mod;
}

本文作者:Jimmy-LEEE

本文链接:https://www.cnblogs.com/redacted-area/p/18389462

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Jimmy-LEEE  阅读(10)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起