……

解题报告:luogu P1445

题目链接:P1445 [Violet]樱花
数学题真的不会了,只推出了浅显的一步,真的菜。
易得到:

\[xy=(x+y)n! \]

移项然后两边同时间上\((n!)^2\),构造平方数:

\[(n!)^2=(n!)^2+(x+y)n!-xy \]

右边十字相乘因式分解:

\[(n!)^2=(n!-x)(n!-y) \]

\(a=n!-x,b=n!-y\),那么:

\[(n!)^2=ab \]

显然\(a,b\)\((n!)^2\)的因子,且\(a,b\)\(x,y\)一一对应,那么我们只需求\((n!)^2\)的因子的因子个数即可。
我们设

\[n!=\prod\limits_{i=1}^mp_i^{k_i} \]

那么\((n!)^2\)的因子个数为:

\[\prod\limits_{i=1}^m(2k_i+1) \]

我们只需考虑如何在线性复杂度内对\(n!\)进行质因数分解。
经过探索,我们得到一个优秀的方法:
先筛出\(1\)\(n\)内的质数,然后考虑:

\[ans=\sum\limits_{p\in prime}^n\sum\limits_{i=1}^{p^i\leqslant n} \left\lfloor\dfrac{n}{p^i}\right\rfloor \]

然后模拟即可,并不会证明复杂度,但似乎不会超过\(\mathcal O(n)\),记得把\(long\;long\)落实即可。

\(Code\):

#include<iostream> 
#include<cstdio>
#include<cmath>
using namespace std;
const int mod=1e9+7;
int prime[1000005],cnt=0,vis[1000005]; 
void get_prime(int n)
{
    vis[1]=1;
    for(int i=2;i<=n;i++)
    {
    	if(!vis[i]) prime[++cnt]=i;
    	for(int j=1;j<=cnt&&(prime[j]*i)<=n;j++)
    	{
    		vis[i*prime[j]]=true;
    		if(i%prime[j]==0) break;
	}
	return;
    }
}
int n;
long long ans=1;
int main()
{
	scanf("%d",&n);
	get_prime(n);
	for(int i=1;i<=cnt;i++)
	{
		long long j=prime[i];
		long long now=0;
		while(j<=n) now+=(n/j)%mod,j*=(long long)prime[i];
		ans=ans*(2*now%mod+1)%mod;
	}

	printf("%lld\n",ans%mod);
	return 0;
}
posted @ 2020-03-31 10:12  童话镇里的星河  阅读(125)  评论(1编辑  收藏  举报