bzoj 2721

版权声明:本博客中有原创标签的内容均为博主原创,转载请注明出处! https://blog.csdn.net/lleozhang/article/details/83415995

 题解:首先推一发式子:

原式:\large \tfrac{1}{x}+\tfrac{1}{y}=\tfrac{1}{n!}

通分,移项:

\large n!(x+y)=xy

打开,合并:

\large n!y=(y-n!)x

再移项,得:

\large x=\tfrac{n!y}{y-n!}

设:

\large t=y-n!

那么:

\large y=t+n!

代入:

\large x=\tfrac{n!(t+n!)}{t}

化简:

\large x=n!+\tfrac{(n!)^{2}}{t}

因为x是整数,所以x的数量显然为能使\large \tfrac{(n!)^{2}}{t}取得整数的t的个数,也就是求\large (n!)^{2}的约数个数

而根据约数个数和公式\large s=\prod_{i=1}^{n}(ci+1)(设一个数\large x=\prod_{i=1}^{n}pi^{ci})

可以将前n个数质因子分解,然后将质因子的幂次相乘,最后将所有幂次*2+1后乘在一起即可。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define ll long long
#define mode 1000000007
#define maxn 1000000
using namespace std;
ll fac[1000005];
ll pri[1000005];
bool used[1000005];
int tot=0;
int n;
void init()
{
	scanf("%d",&n);
	for(int i=2;(ll)i*i<=n;i++)
	{
		if(!used[i])
		{
			pri[++tot]=i;
		}
		for(int j=1;j<=tot&&(ll)i*pri[j]<=n;j++)
		{
			used[i*pri[j]]=1;
			if(i%pri[j]==0)
			{
				break;
			}
		}
	}
	for(int i=2;i<=n;i++)
	{
		int t=i;
		for(int j=1;(ll)pri[j]*pri[j]<=t&&j<=tot;j++)
		{
			while(t%pri[j]==0)
			{
				fac[pri[j]]++;
				t/=pri[j];	
				if(fac[pri[j]]>=mode)
				{
					fac[pri[j]]-=mode;
				}
			}
		}
		if(t!=1)
		{
			fac[t]++;
			if(fac[t]>=mode)
			{
				fac[t]-=mode;
			}		
		}
	}  
	ll ans=1;
	for(int i=1;i<=n;i++)
	{
		fac[i]<<=1;
		fac[i]%=mode;
		ans*=(fac[i]+1);
		ans%=mode;
	}
	printf("%lld\n",ans);
}
int main()
{
	init();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lleozhang/article/details/83415995
今日推荐