hdu6134莫比乌斯反演+脑洞


题解:






现在我们只要求出g(n)就能解决此题了,ans(n)枚举因子nlogn筛一下就好了

公式秒推,分块求g(n):O(n*sqrtn*logn)秒T,尝试分块打表200*5000求g(n):还是T了

尝试OEIS才发现g(n)有递推公式g(n)=g(n-1)+d(n-1)+1,d(n)是n的因子个数,脑洞不够啊

如果是向下取整求和也有公式=sum(d(i))

g++ 405ms

扫描二维码关注公众号,回复: 1544481 查看本文章
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
ll mu[1000005];bool isp[1000005];int pri[1000005];
ll ans[1000005];ll g[1000005];ll d[1000005];
int p=0;
void init(ll n)
{
	isp[1]=1;mu[1]=1;
	for(ll i=2;i<=n;i++)
	{
		if(!isp[i])pri[++p]=i,	mu[i]=-1;
		for(ll 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];
		}
	}
}
void init2(int n)
{
	for(int i=1;i<=1000000;i++)
		for(int j=i;j<=1000000;j+=i)
			d[j]+=1;
	for(int i=1;i<=1000000;i++)g[i]=(g[i-1]+d[i-1]+1+mod)%mod;
}
int main()
{
	ll n;init(1000002);init2(1000002);
	for(int i=1;i<=1000000;i++)
		for(int j=i;j<=1000000;j+=i)
			ans[j]+=mu[i]*g[j/i]%mod;//;
	for(int i=1;i<=1000000;i++)
		ans[i]+=ans[i-1]%mod;
	while(~scanf("%lld",&n))
		cout<<(ans[n]+mod)%mod<<endl;
}

猜你喜欢

转载自blog.csdn.net/animalcoder/article/details/80293899