题目大意:求
首先我们有一个很神的结论:
这个结论是怎么来的呢?我们可以先证明这个:
显然这个式子的前缀和就是上面的式子
现在我们来证明这个式子是对的
我们分开讨论每一个质数
不妨设
那么左式中
右式中只考虑
因此等式成立,原式得证。
然后怎么搞还用我说么= =?
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 50500
using namespace std;
int n,m;
int mu[M],d[M],cnt[M],prime[M],tot;
bool not_prime[M];
void Linear_Shaker()
{
int i,j;
mu[1]=1;d[1]=1;
for(i=2;i<=50000;i++)
{
if(!not_prime[i])
{
prime[++tot]=i;
mu[i]=-1;
d[i]=2;
cnt[i]=1;
}
for(j=1;prime[j]*i<=50000;j++)
{
not_prime[prime[j]*i]=true;
if(i%prime[j]==0)
{
mu[prime[j]*i]=0;
d[prime[j]*i]=d[i]/(cnt[i]+1)*(cnt[i]+2);
cnt[prime[j]*i]=cnt[i]+1;
break;
}
mu[prime[j]*i]=-mu[i];
d[prime[j]*i]=d[i]<<1;
cnt[prime[j]*i]=1;
}
}
for(i=1;i<=50000;i++)
{
mu[i]+=mu[i-1];
d[i]+=d[i-1];
}
}
long long Solve()
{
long long re=0;
int i,last;
if(n>m) swap(n,m);
for(i=1;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
re+=(long long)(mu[last]-mu[i-1])*d[n/i]*d[m/i];
}
return re;
}
int main()
{
int T;
Linear_Shaker();
for(cin>>T;T;T--)
{
scanf("%d%d",&n,&m);
printf("%lld\n",Solve());
}
return 0;
}
BZOJ 3994 Sdoi2015 约数个数和 莫比乌斯反演
原文地址:http://blog.csdn.net/popoqqq/article/details/45078079