解题报告: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;
}