莫比乌斯反演推求和公式交换枚举顺序的骚技巧

技巧1:对这种求和交换顺序

技巧2:对这种求和交换顺序,看下面过程

A.牛客网练习赛25A,枚举约数个数和

\large ans=\sum_{i=1}^{n}\sum_{d|i}=\sum_{i=1}^{n}\sum_{d=1}^{n}[d|i]//注意这里将d的范围提高到n,对结果无影响

\large ans=\sum_{d=1}^{n} \left \lfloor \frac{n}{d} \right \rfloor//令i=id,交换求和顺序,从枚举i变成枚举d

 

B.51nod1742,莫比乌斯反演

\large ans=\sum_{t=1}^{n}\sum_{d|t}[if-d-has-square-factor]//有平方因子贡献为1

\large ans=\sum_{t=1}^{n}\sum_{d|t}(1-\sum_{i^2|d}\mu(i))//1-有平方因子就是无平方因子的贡献

分别求和,前面跟A一模一样,后面

//同样提高d求和的上限到n,然后变成这样

\large fuck=\sum_{t=1}^{n}\sum_{d|t}\sum_{i^2|d}\mu(i)\large =\sum_{t=1}^{n}\sum_{d=1}^{n}[d|t]\sum_{i^2|d}\mu(i)

//令t=td,交换求和就会得到下面,然后提高i求和上限到n,

\large fuck=\sum_{d=1}^{n} \left \lfloor \frac{n}{d} \right \rfloor \sum_{i^2|d}\mu(i) =\sum_{d=1}^{n} \left \lfloor \frac{n}{d} \right \rfloor\sum_{i=1}^{n}\mu(i)[i^2|d]

//令d=i^2*d,交换求和顺序得到下面,因为i*i<=n,所以i枚举到sqrt(n)即可

\large fuck=\sum_{i=1}^{n}\mu(i) \sum_{d=1}^{n/i^2} \left \lfloor \frac{n}{i^2d} \right \rfloor =\sum_{i=1}^{\sqrt{n}}\mu(i)*Get1(\left \lfloor \frac{n}{i^2} \right \rfloor )

Get1()就是上面A.求的那个

#include<bits/stdc++.h>
#define ll long long
using namespace std; 
int pri[45005];bool isp[45005];int mu[45005];ll F[10000005];
map<int,ll>mp;
void init(int n,int pp)//预处理sqrtn个mu 
{
    int p=0;mu[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(isp[i]==0)  pri[++p]=i,mu[i]=-1;
        for(int j=1;j<=p&&i*pri[j]<=n;j++)
        {
            isp[i*pri[j]]=1;
            if(i%pri[j]==0)
            {
                mu[i*pri[j]]=0;break;
            }
            else mu[i*pri[j]]=-mu[i];
        }
    }
}
ll get1(ll n)//加个记忆化 46ms T很小,map可不加 
{
	if(n<=10000000&&F[n])return F[n];
	if(mp[n])return mp[n];
	ll ans=0;int nxt=0;
	for(int i=1;i<=n;i=nxt+1)
	{
		nxt=n/(n/i);
		ans+=1ll*(n/i)*(ll)(nxt-i+1);
	}
	if(n<=10000000) return F[n]=ans;
	return mp[n]=ans;
}
int main()
{
	
	ll n,n1;scanf("%lld %lld",&n,&n1);n--;
	init((int)sqrt(n1+0.5),1e9+7);
	ll ans=get1(n);
	for(int i=1;i<=n/i;i++)
		ans-=1ll*mu[i]*get1(n/i/i);
	
	ll ans1=get1(n1);
	for(int i=1;i<=n1/i;i++)
		ans1-=1ll*mu[i]*get1(n1/i/i);
	printf("%lld\n",ans1-ans);
}

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值