无聊的水题
DLS 是一个喜欢玩游戏的男生。
今天他从朋友那里看到了 (n) 件武器,其中第 (i) 件武器的威力值为 (i)。
他观察了这 (n) 件武器许久,打算买下其中若干件武器,但他想用买下的武器的威力值组合出任意威力值,其中每一件武器已经的威力值可以叠加,甚至可以减去。
例如一个威力值为 (3) 的武器,可以组合成的威力值为 (dots,-6,-3,0,3,6,dots)。
他想找出所有满足以上条件的买下装备的方案,但方案数量实在太多了。你能帮他计算一下吗?答案对 (10^9+7) 取模。
(n leq 10^{11})。
题解
https://www.alpha1022.me/articles/lg-5218.htm
使用结合律证明裴蜀定理对三个及以上的元素有效。所以问题转化为有多少种选数的方案使得选出的数的 (gcd = 1)。
设 (f(x)) 表示使得选出的数的 (gcd=x) 的方案数。那么答案就是 (f(1))。
设 (F(x)) 表示使得选出的数的 (gcd) 是 (x) 的倍数的方案数。那么有
[F(x)=2^{lfloor n/x
floor}-1\
F(x)=sum_{x|y}f(y)
]
出现了莫比乌斯反演不常见的第二种形式。
[f(x)=sum_{x|y}muleft(frac{y}{x}
ight)F(y)
]
这也不是狄利克雷卷积,看起来没法做。解决办法是直接代入 (f(1))。
[f(1)=sum_{i=1}^nmu(i)F(i)\
=sum_{i=1}^nmu(i)(2^{lfloor n/i
floor}-1)
]
对于指数做数论分块,对于 (mu) 杜教筛就好了。
时间复杂度 (O(n^{2/3}))。
CO int N=1e7+10;
int pri[N],tot,mu[N];
int64 n;
int sum[N];
int calc(int64 n){
if(n<N) return mu[n];
if(sum[::n/n]) return sum[::n/n];
int ans=1;
for(int64 l=2,r;l<=n;l=r+1){
r=n/(n/l);
ans=add(ans,mod-mul((r-l+1)%mod,calc(n/l)));
}
return sum[::n/n]=ans;
}
int main(){
mu[1]=1;
for(int i=2;i<N;++i){
if(!pri[i]) pri[++tot]=i,mu[i]=mod-1; // edit 1: mod-1
for(int j=1;j<=tot and i*pri[j]<N;++j){
pri[i*pri[j]]=1;
if(i%pri[j]==0) break;
mu[i*pri[j]]=mod-mu[i];
}
}
for(int i=1;i<N;++i) mu[i]=add(mu[i],mu[i-1]);
read(n);
int ans=0;
for(int64 l=1,r;l<=n;l=r+1){
r=n/(n/l);
ans=add(ans,mul(add(calc(r),mod-calc(l-1)),fpow(2,n/l%(mod-1))-1));
}
printf("%d
",ans);
return 0;
}