bzoj P1968

这题是十分经典的数学题,在其他各大oj也都有类似(相同)的题目

但是,我们还是从头开始说

首先,这道题肯定不会是递推,因为给出的f[1~6]就已经没有递推性了。。

所以,应该是一道模拟题(?)

算法一:从1循环到n,每次枚举1~i的所有数,判断是否为因数,ans++。。。

复杂度比O(n^2)小一些。。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,ans;
int main(){
  scanf("%d”,&n);
  
  for(int i=1;i<=n;i++)

    for(int j=1;j<=i;j++)

      if(i%j==0) ans++;

  printf("%d",ans);
  return 0;
}

 

 

当然,会超时。。。

算法二:利用小学数学知识(以及初中的根号),每次从1循环到n,枚举1~sqrt(n)(n的根号),

判断i是否为因数,如果是,则必然有两个因数组成i,于是ans+=2。。。(这里注意特判一下sqrt(n)的情况,这样的情况ans只加一)

复杂度O(n*sqrt(n)),n<=10^6,最坏复杂度为10^9,会超时。。

代码如下

#include<bits/stdc++.h>
using namespace std;
long long n,ans;
int solve(int x){
int cnt=0;
for(int i=1;i<=sqrt(x);i++)
if(x%i==0){
cnt+=2;
if(i==sqrt(x)) cnt--;
}
return cnt;
}
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++) ans+=solve(i);
printf("%lld",ans);
return 0;
}

算法三:用筛法,但是不是正常的筛法:

因数的范围是在1~n之间的,所以可以倒着考虑,一个数有几个在1~n范围内的倍数呢?

因此可以枚举每个1~n的因数,求出他有几个倍数,然后ans加上倍数个数就行了(连根号都不用特判)。。

代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) ans+=n/i;
printf("%d",ans);
return 0;
}

 

posted @ 2017-10-17 19:36  Accelerator-D-x  阅读(106)  评论(0编辑  收藏  举报