解题报告: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!=prodlimits_{i=1}^mp_i^{k_i} ]

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

[prodlimits_{i=1}^m(2k_i+1) ]

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

[ans=sumlimits_{pin prime}^nsumlimits_{i=1}^{p^ileqslant n} leftlfloordfrac{n}{p^i} ight floor ]

然后模拟即可,并不会证明复杂度,但似乎不会超过(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
",ans%mod);
	return 0;
}
原文地址:https://www.cnblogs.com/tlx-blog/p/12603339.html