zoukankan      html  css  js  c++  java
  • 洛谷P1865 A%B Problem

    题面:

     

     这道题很明显是一道数论的题目,涉及的内容主要为素数的问题。首先看数据范围,其实这道题的数据范围是很水的。因此在这里主要介绍2种方法。

    法一,首先题目给出了给定区间右端点的最大值,因此我们对于每一个输入的l和r,要先进行判断其是否合法,只有合法的区间才能进一步处理。而合法的标准是右端点r<=m且左端点l>=1(注意这里要小心,不要想当然,题目中出了四个点来卡它)。

    因此我们可以对于每一个给定的合法区间l到r,枚举l到r中的所有元素,依次判断该元素是否为素数。如果为素数,则cnt++。这里对于素数的判断我使用了O(√n)的试除法。很明显该方法时间复杂度过大。

    代码(含注释):

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int n,m,i,l,r,h,cnt;
     5 inline bool prime(int n){//判断每一个数是否为素数
     6     if(n<2){//<2的数一定不是素数,要小心
     7         return false;
     8     }else{
     9         int j;
    10         for(j=2;j*j<=n;j++){//进行枚举
    11             if(n%j==0){//如果n有2~√n的质因子,则n一定非质
    12                 return false;
    13             }
    14         }
    15     }
    16     return true;
    17 }
    18 int main(){
    19     scanf("%d %d",&n,&m);
    20     for(i=1;i<=n;i++){
    21         scanf("%d %d",&l,&r);
    22         if(r>m||l<1){//判断区间是否合法
    23             printf("Crossing the line
    ");
    24         }else{
    25             cnt=0;//统计每个区间内的素数个数
    26             for(h=l;h<=r;h++){
    27                 if(prime(h)==true){
    28                     cnt++;
    29                 }
    30             }
    31             printf("%d
    ",cnt);
    32         }
    33     }
    34     return 0;
    35 }

    分数:81分(完全没有想到!)

    法二,既然法一出现了超时,那我们就要想方法进行优化。在法一中,TLE的主要原因便是对于同一个素数需要进行多次判断。而如果能够在一定的预处理基础上将O(√n)变成O(1),那么时间就加快了。

    题目明显预先给出了r的最大值,目的即是启发我们进行预处理。因此我们可以在O(n)的时间复杂度内预先找出1~m中的质数(我使用了线性筛),然后进行寻找和统计。

    代码(含注释):

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int n,m,i,j,l,r,h,cnt,num;
     5 int prime[100000005],v[100000005];
     6 int main(){
     7     scanf("%d %d",&n,&m);
     8     num=0;//质数数量
     9     for(i=2;i<=m;i++){
    10         if(v[i]==0){//i是质数 
    11             v[i]=i;//质数的最小质因子是他自己
    12             prime[++num]=i;//记录质数 
    13         }
    14         for(j=1;j<=num;j++){//给当前的数i乘上一个质因子 
    15             if(prime[j]>v[i]||prime[j]>m/i){
    16                 break;//i有比prime[j]更小的质因子,或者超出n的范围 
    17             }
    18             v[i*prime[j]]=prime[j];
    19         }
    20     }
    21     for(i=1;i<=n;i++){
    22         scanf("%d %d",&l,&r);
    23         if(r>m||l<1){
    24             printf("Crossing the line
    ");
    25         }else{
    26             cnt=0;
    27             for(h=1;h<=m;h++){
    28                 if(prime[h]>=l&&prime[h]<=r){
    29                     cnt++;
    30                 }
    31             }
    32             printf("%d
    ",cnt);
    33         }
    34     }
    35     return 0;
    36 }

    即可获得AC。

  • 相关阅读:
    最大子数组1
    大道至简阅读笔记03
    I-think-3
    第3周学习进度
    大道至简阅读笔记02
    四则运算题3
    大道至简阅读笔记01
    第2周学习进度
    构建之法阅读笔记03
    按Right-BICEP的测试用例
  • 原文地址:https://www.cnblogs.com/qianr/p/13280052.html
Copyright © 2011-2022 走看看