zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    8.8集训
    8.7集训
    8.6集训
    poj 2492
    埃氏筛法
    并查集板子
    2018级程序能力实训第二次上机考试
    网络流
    活动安排问题
    等价类
  • 原文地址:https://www.cnblogs.com/heqingyu/p/7683494.html
Copyright © 2011-2022 走看看