zoukankan      html  css  js  c++  java
  • HDU 4548 美素数 (线段树)

    美素数

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
    Total Submission(s): 374    Accepted Submission(s): 159


    Problem Description
      小明对数的研究比较热爱,一谈到数,脑子里就涌现出好多数的问题,今天,小明想考考你对素数的认识。
      问题是这样的:一个十进制数,如果是素数,而且它的各位数字和也是素数,则称之为“美素数”,如29,本身是素数,而且2+9 = 11也是素数,所以它是美素数。
      给定一个区间,你能计算出这个区间内有多少个美素数吗?
     
    Input
    第一行输入一个正整数T,表示总共有T组数据(T <= 10000)。
    接下来共T行,每行输入两个整数L,R(1<= L <= R <= 1000000),表示区间的左值和右值。
     
    Output
    对于每组数据,先输出Case数,然后输出区间内美素数的个数(包括端点值L,R)。
    每组数据占一行,具体输出格式参见样例。
     
    Sample Input
    3 1 100 2 2 3 19
     
    Sample Output
    Case #1: 14 Case #2: 1 Case #3: 4
     
    Source
     
    Recommend
    liuyiding

    1,打表+枚举:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    const int N=1000010;
    
    int isprime[N],prime[N],res[N];
    
    void getprime(){
        int i,j;
        prime[0]=0;
        for(i=0;i<N;i++)
            isprime[i]=1;
        for(i=2;i<N;i++)
            if(isprime[i]){
                prime[++prime[0]]=i;
                for(j=2;i*j<N;j++)
                    isprime[i*j]=0;
            }
    }
    
    int isok(int x){
        for(int i=2;i*i<=x;i++)
            if(x%i==0)
                return 0;
        return 1;
    }
    
    int cnt;
    
    void Init(){
        getprime();
        cnt=0;
        int tmp;
        for(int i=1;i<=prime[0];i++){
            tmp=prime[i];
            int k=0;
            while(tmp){
                k+=tmp%10;
                tmp/=10;
            }
            if(isok(k))
                res[cnt++]=prime[i];
        }
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        int t;
        int l,r;
        int cases=0;
        scanf("%d",&t);
        Init();
        while(t--){
            scanf("%d%d",&l,&r);
            int ans=0;
            for(int i=0;i<cnt && res[i]<=r;i++)
                if(res[i]>=l)
                    ans++;
            printf("Case #%d: %d\n",++cases,ans);
        }
        return 0;
    }

    2,线段树,,

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int N=1000010;
    
    #define L(rt) (rt<<1)
    #define R(rt) (rt<<1|1)
    
    struct Tree{
        int l,r;
        int num;
    }tree[N<<2];
    
    int a[N]={0,0,1,1},ans;
    
    int get(int x){
        int res=0;
        while(x){
            res+=x%10;
            x/=10;
        }
        return res;
    }
    
    void PushUp(int rt){
        tree[rt].num=tree[L(rt)].num+tree[R(rt)].num;
    }
    
    void build(int L,int R,int rt){
        tree[rt].l=L;
        tree[rt].r=R;
        tree[rt].num=0;
        if(tree[rt].l==tree[rt].r){
            if(a[L]==1 && a[get(L)]==1)
                tree[rt].num=1;
            return ;
        }
        int mid=(L+R)>>1;
        build(L,mid,L(rt));
        build(mid+1,R,R(rt));
        PushUp(rt);
    }
    
    void query(int L,int R,int rt){
        if(tree[rt].l==L && tree[rt].r==R){
            ans+=tree[rt].num;
            return ;
        }
        if(tree[rt].l==tree[rt].r)
            return ;
        int mid=(tree[rt].l+tree[rt].r)>>1;
        if(R<=mid)
            query(L,R,L(rt));
        else if(L>mid)
            query(L,R,R(rt));
        else{
            query(L,mid,L(rt));
            query(mid+1,R,R(rt));
        }
    }
    
    void Init(){
        int i,j,k=4;
        for(i=5;i<N;i+=k^=6){       //从5以后,每个素数的间隔一般为2,或者4,6之类的,这个取反操作正好可以减少循环次数
            if(a[i]==0){
                a[i]=1;
                for(j=i;j<=N/i;j++)
                    a[j*i]=-1;
            }
        }
        build(0,N-1,1);
    }
    
    int main(){
    
        //freopen("input.txt","r",stdin);
    
        Init();
        int t;
        scanf("%d",&t);
        int a,b,cases=0;
        while(t--){
            scanf("%d%d",&a,&b);
            ans=0;
            query(a,b,1);
            printf("Case #%d: %d\n",++cases,ans);
        }
        return 0;
    }
  • 相关阅读:
    第36课 经典问题解析三
    第35课 函数对象分析
    67. Add Binary
    66. Plus One
    58. Length of Last Word
    53. Maximum Subarray
    38. Count and Say
    35. Search Insert Position
    28. Implement strStr()
    27. Remove Element
  • 原文地址:https://www.cnblogs.com/jackge/p/3087685.html
Copyright © 2011-2022 走看看