题目来源:
WUSTOJ http://acm.wust.edu.cn/problem.php?id=2263&soj=0
洛谷:https://www.luogu.org/problemnew/show/P1445
★鸽了一个月,我又回来了(然而马上要期末了 )
相关知识:
首先是质数的筛法,常用的就是埃氏筛法,然后还有欧拉筛法,等等之类的,模板之后贴叭
思路:
首先说一下证明过程,如下
参考巨佬博客:http://m-sea-blog.com/archives/460/
我还看过一种证明方法,菜鸡表示不太好理解awa 就不证了
所以我们要先求出的就是从1到n的质数因子的指数,然后乘在一起就ok了
数组num 代表的是ci
数组prime 用来保存质数
WA代码:
虽然有了思路,但仍然不一定AC,因为复杂度也会卡WA
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
const int mod=1e9+7;
typedef long long ll;
int prime[maxn],num[maxn];
bool vis[maxn];
int main()
{
int n;
cin>>n;
memset(vis,true,sizeof vis);
vis[0]=vis[1]=0;
int cnt=0;
for(int i=2;i<=n;i++){
if(vis[i]){
prime[++cnt]=i;
}
for(int j=2;j<=n/i;j++){
vis[j*i]=0;
}
}
memset(num,0,sizeof num);
for(int i=2;i<=n;i++){
int k=i;
for(int j=1;j<=cnt;j++){
while(k%prime[j]==0) k/=prime[j],num[prime[j]]++;
if(k==1) break;
}
}
ll ans=1;
for(int i=1;i<=cnt;i++){
ans=(ans*(2*num[prime[i]]+1))%mod;
}
cout<<ans<<endl;
return 0;
}
分析一下复杂度,前面的埃氏筛法 n*loglogn 接近o(n),但是后面的求ci的时候复杂度高了
改成了这样
memset(num,0,sizeof num);
for(int i=1;i<=cnt;i++){
for(int j=prime[i];j<=n;j*=prime[i]){
num[i]+=n/j;
}
}
还是有问题,你们发现了没[ 滑稽 ]
这个地方n比较大的话,j就爆了,要开long long
awa
最终代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
const int mod=1e9+7;
typedef long long ll;
int prime[maxn];
ll num[maxn];
bool vis[maxn];
int main()
{
int n;
cin>>n;
memset(vis,true,sizeof vis);
vis[0]=vis[1]=0;
int cnt=0;
for(int i=2;i<=n;i++){
if(vis[i]){
prime[++cnt]=i;
}
for(int j=2;j<=n/i;j++){
vis[j*i]=0;
}
}
memset(num,0,sizeof num);
for(int i=1;i<=cnt;i++){
for(ll j=prime[i];j<=n;j*=prime[i]){
num[i]+=n/j;
}
}
ll ans=1;
for(int i=1;i<=cnt;i++){
ans=(ans*(2*num[i]+1))%mod;
}
cout<<ans<<endl;
return 0;
}