• CodeForces


    pro:给定三个整数L,R,P求[L,R]区间的整数有多少个是以P为最小因子的。L,R,P<2e9;

    sol:

    一: 比较快的做法是,用函数的思想递归。

        用solve(N,P)表示求1到N有多少数字多少个的最小因子是P;

         1,首先P是合数,或者N<P;solve=0;

         2,否则,如果P*P>=N;solve=1;

         3,solve=N/P-solve(N/P,i);     2<=i<P

     由于P主要分布在sqrt(N),而且N每次log级别减小,所以收缩得很快。具体的复杂度我证明不来,但是感觉过程和min25筛差不多。 (62ms

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=200010;
    bool check(int P)
    {
        for(int i=2;i*i<=P;i++)
          if(P%i==0) return false;
        return true;
    }
    int solve(int N,int P)
    {
        if(!check(P)||N<P) return 0;
        if(N/P<P) return 1;
        int res=N/P;
        rep(i,2,P-1) res-=solve(N/P,i);
        return res;
    }
    int main()
    {
        int A,B,P;
        scanf("%d%d%d",&A,&B,&P);
        printf("%d
    ",solve(B,P)-solve(A-1,P));
        return 0;
    }

    二:当时还不流行min25筛,否则这题大部分人都可以套板子了。我们知道min25的过程其实就是每次可以得到最小素因子为p的数的个数(或者之和),所以改一下板子即可(128ms

    #include<bits/stdc++.h>
    using namespace std;
    #define ll int
    const int maxn=200010;
    ll Sqr,vis[maxn],pri[maxn],tot,m,id1[maxn],id2[maxn];
    ll g[maxn],w[maxn]; //sp前i个素数之和。
    void Sieve(int n)
    {
        tot=0; vis[1]=1;
        for(int i=2;i<=n;i++){
            if(!vis[i]) pri[++tot]=i;
            for(int j=1;pri[j]<=n/i;j++){
                   vis[i*pri[j]]=1;
                if(i%pri[j]==0) break;
            }
        }
    }
    bool check(int P)
    {
        for(int i=2;i*i<=P;i++)
          if(P%i==0) return false;
        return true;
    }
    ll solve(ll n,ll K)
    {
        if(n<K) return 0;
        if(!check(K)) return 0;
        if(K>n/K) return 1;
        Sqr=sqrt(n); Sieve(Sqr); ll res=0; m=0;
        for(ll i=1,j;i<=n;i=j+1){
            j=n/(n/i); w[++m]=n/i;
            if(w[m]<=Sqr) id1[w[m]]=m;
            else id2[n/w[m]]=m;
            g[m]=w[m]-1; //1到n的素数个数,先设为n-1(1不考虑
        }
        for(int j=1;j<=tot;j++){
          for(int i=1;i<=m&&pri[j]<=w[i]/pri[j];i++){
            int k=(w[i]/pri[j]<=Sqr)?id1[w[i]/pri[j]]:id2[n/(w[i]/pri[j])];
            g[i]=g[i]-(g[k]-(j-1));
            if(pri[j]==K&&i==1) res+=g[k]-(j-1); //K去筛,[1,N]时
          }
        }
        return res+1;//加上素数自己
    }
    int main()
    {
        int l,r,k;
        scanf("%d%d%d",&l,&r,&k);
        printf("%d
    ",solve(r,k)-solve(l-1,k));
        return 0;
    }
  • 相关阅读:
    js 实现加入收藏/加入首页功能
    js 获取网页宽/高度
    js 飞机大战
    js 实现分享功能
    前端开发的工具,库和资源总结
    网站更新后客户端缓存问题
    js 实现图片无限横向滚动效果
    js 实现 文字打印效果
    js 构造函数创建钟表
    Css3 实现关键帧动画
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10853374.html
Copyright © 2020-2023  润新知