题目链接: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;
}