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

技巧2:对这种求和交换顺序,看下面过程
A.牛客网练习赛25A,枚举约数个数和
//注意这里将d的范围提高到n,对结果无影响
//令i=id,交换求和顺序,从枚举i变成枚举d
B.51nod1742,莫比乌斯反演
//有平方因子贡献为1
//1-有平方因子就是无平方因子的贡献
分别求和,前面跟A一模一样,后面
//同样提高d求和的上限到n,然后变成这样

![\large =\sum_{t=1}^{n}\sum_{d=1}^{n}[d|t]\sum_{i^2|d}\mu(i)](https://private.codecogs.com/gif.latex?%5Clarge%20%3D%5Csum_%7Bt%3D1%7D%5E%7Bn%7D%5Csum_%7Bd%3D1%7D%5E%7Bn%7D%5Bd%7Ct%5D%5Csum_%7Bi%5E2%7Cd%7D%5Cmu%28i%29)
//令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]](https://private.codecogs.com/gif.latex?%5Clarge%20fuck%3D%5Csum_%7Bd%3D1%7D%5E%7Bn%7D%20%5Cleft%20%5Clfloor%20%5Cfrac%7Bn%7D%7Bd%7D%20%5Cright%20%5Crfloor%20%5Csum_%7Bi%5E2%7Cd%7D%5Cmu%28i%29%20%3D%5Csum_%7Bd%3D1%7D%5E%7Bn%7D%20%5Cleft%20%5Clfloor%20%5Cfrac%7Bn%7D%7Bd%7D%20%5Cright%20%5Crfloor%5Csum_%7Bi%3D1%7D%5E%7Bn%7D%5Cmu%28i%29%5Bi%5E2%7Cd%5D)
//令d=i^2*d,交换求和顺序得到下面,因为i*i<=n,所以i枚举到sqrt(n)即可

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);
}