您的位置:首页 > 其它

bzoj 2721(线性筛)(约数个数)

2017-10-18 19:20 211 查看
传送门

题解:

设y=n!+t,化简后知x=(n!)^2/t+n!。

所以求(n!)^2的约数个数即可。

约数个数公式:

若x=(p1^k1)*(p2^k2)*...*(pm*km),则x的约数个数d(x)=(k1+1)*(k2+1)*...*(km+1)

所以后面枚举每个预先线性筛筛出的质数,计算它的k,由于是(n!)^2,所以每一个质数的贡献是ki*2+1,最后乘起来即可。

复杂度是个好问题,实测出来大概是3n?我觉得应该是1~n每个数分解质因数后的质因数指数之和?

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=1e6+4;
const ll MOD=1e9+7;
int n;
int prime[MAXN],cnt[MAXN],tot=0,ans=1;
bool vis[MAXN];
inline void linear_shaker() {
for (register int i=2;i<MAXN;++i) {
if (!vis[i]) prime[++tot]=i;
for (int j=1;j<=tot&&i*prime[j]<MAXN;++j) {
vis[i*prime[j]]=true;
if (i%prime[j]==0) break;
}
}
prime[++tot]=MOD;
}
int main() {
linear_shaker();
scanf("%d",&n);
// int clo=0;
for (int i=1;prime[i]<=n;++i)
for (int j=prime[i];j<=n;j+=prime[i])
for (int k=j;k%prime[i]==0;k/=prime[i])
++cnt[i];//,++clo;
for (int i=1;i<=tot;++i)
ans=1ll*ans*(cnt[i]<<1|1)%MOD;
printf("%d\n",ans);
// printf("time==%d\n",clo);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线性筛 约数个数