文章目录
- 题目描述
- 解析
- 代码
题目描述
数据范围有误!应该是不超过1e6
解析
容易推出:
y=(x∗*∗n!)/(x-n!)
换元,令t=x-n!
则:
y=n!+(n!)2/t
因为x、y都与t一一对应
所以本题就是求 (n!)2 的因数个数
我们求出n!的质因数分解的话,问题就好办了
问题在于怎么求
我们可以在预处理出[1,n]的素数表后,使用类似筛法的操作
for (int i = 1; i <= tot; i++) {for (ll j = prime[i]; j <= n; j *= prime[i]) {c[i] += n / j;c[i] %= mod;}}
为什么可以这样
我们举个例子
当n=27,模数为3时
我们就是要求横线出现的次数
回去看代码
j的每一层循环其实就是在算某一层的线段个数
最后加在一起
还是挺巧妙的
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e7+100;
const int M=1e7+100;
const int mod=1e9+7;
ll n;
int prime[N],v[N],tot,c[N];
void findprime(){for(int i=2;i<=n;i++){if(!v[i]){v[i]=i;prime[++tot]=i;}for(int j=1;j<=tot;j++){int now=prime[j];if(now>n/i||now>v[i]) break;v[now*i]=now;}}return;
}int main() {scanf("%lld",&n);findprime();for(int i=1;i<=tot;i++){for(ll j=prime[i];j<=n;j*=prime[i]){c[i]+=n/j;c[i]%=mod;}}ll ans=1;for(int i=1;i<=tot;i++){ans=(ans*(2*c[i]+1))%mod;}printf("%lld\n",ans);return 0;
}