• 数论题目


    素数个数

     

    样例输入

    4
    2 11
    2 98
    2 1000000
    999999000000 1000000
    
    

    样例输出

    6
    25
    78498
    36400



    直接上代码吧,注释很全了
    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    const int N = 1e6 + 5;
    ll n, m, pr[N], tot, s[N];
    bool vis[N];
    
    int main() {
        int T;
        scanf("%d", &T);
        while (T--) {
            scanf("%lld%lld", &n, &m);
            memset(vis, 0, sizeof vis);
            ll total = m + 1;//将n到n+m的数全认为是质数,也就是这个区间上数的个数总数 
            //区间里数的总数减去该区间所有合数,最终就是质数个数 
            //下面开始找合数 
            for (ll i = 2; i <= 1e6 && i <= n + m; i++)//从2到1e6枚举因数 
            //因数枚举的范围2-1e6,i<=n+m是一个小剪枝 
                for (ll j = (n / i) * i; j <= n + m; j += i)//(n/i)*i最接近n的i的倍数 
                //j是枚举n到n+m之间i的倍数,他有i这个因子,所以他就是合数了,标记为访问过,防止重复访问 
                    if (j >= n && j != i && !vis[j - n]){
                        //j>=n就排除了(n/i)*i<n的情况 
                        //j != i是因为,当i=j时,不足以证明他是合数 
                        vis[j - n] = 1;//标记为访问过 
                        total--;//找到一个合数,减掉该合数 
                    }
            printf("%lld
    ", total);
        }
    }

     


    视野

    样例1输入

    10
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    

    样例1输出

    1
    3
    7
    11
    19
    23
    35
    43
    55
    63
    

     


     

    因为左上右下两部分是对称的,所以只求一部分即可,最后答案乘以2

    但是,要知道对角线是只有一条的,对角线上只有一个点,

    所以最后乘了2的答案要减去1

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e6 + 5;
    
    int T,C,phi[N], prime[N], tot;
    bool vis[N];
    long long ans;
    
    void getprime(){ //欧拉函数 
        phi[1]=1;
        for (int i = 2; i <= 1e6; i++) {
            if (!vis[i]) {
                prime[++tot] = i;
                phi[i] = i - 1;
            }
            for (int j = 1; j <= tot && i * prime[j] <= 1e6; j++) {
                vis[prime[j] * i] = 1;
                if (i % prime[j] == 0) {
                    phi[i * prime[j]] = phi[i] * prime[j];
                    break;
                } else
                    phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            }
        }
    }
    
    int main() {
        getprime();
        scanf("%d", &T);
        while (T--) {
            ans=0;
            scanf("%d", &C);
            for(int i=1;i<=C;i++)
                ans+=phi[i];
            ans=ans*2-1;//或者写成(ans-1)*2+1 (因为其他地方都有对称的,而对角线上只有一个,所以要-1) 
            printf("%lld
    ", ans); //??
        }
    }

     


     

    Hankson的趣味题

    分解质因数做就ok啦

    图中,

    p1,p2,p3.....是a,b,c,d全部的质因数

    x1,y1,z1,w1....是幂次(不含就记为0)(也就是该数含有多少次的该列的质因子)

    gcd的话,我们来看a,b

    他是有个≥的界或=的界

    若x1=y1,则x分解出来的p1的幂次≥x1即可

    若x2≠y2,则x分解出来的p2的幂次要刚好等于y2

    (因为呢,b是a与x的gcd嘛,b的某质因数的幂次肯定≤a的该质因数的幂次,

    若x2≠y2,则y2一定≤x2,嗯

    x该质因数的幂次不能>y2,要是大于,最大公约数b的该质因数的幂次就会比此时的y2大了)

    lcm的话,就看c,d

    他有个≤的界或=的界

    算法同上啦,仔细分析一下就好啦(其实是我懒得去想了嘿嘿)

    /*存在x使得: x 和 a0的最大公约数是 a1
      x和b0的最小公倍数是b1 ,求x的个数
       
     →x % a1 = 0, a0 % a1 = 0(确定), gcd(x,a0) = a1;  公约数 
       b1 % x = 0, b1 % b0 = 0(确定), lcm(x,b0) = b1;  公倍数 */
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int n,a0,a1,b0,b1;
    
    int gcd(int a,int b){
        return b==0?a:gcd(b,a%b);
    }
    
    int pd(int x){  
        if(x%a1==0) 
            return(gcd(x/a1,a0/a1)==1 && gcd(b1/b0,b1/x)==1);
        return 0;
    }
    
    int main(){
        scanf("%d",&n);
        while(n--){
            ll ans=0;
            scanf("%d%d%d%d",&a0,&a1,&b0,&b1);
            for(int i=1;i*i<=b1;i++){
                if(b1%i==0){  //是公倍数 
                    ans+=pd(i);
                    if(b1!=i){
                        int ii=b1/i;
                        ans+=pd(ii);  //特判 1 1 1 1的状况 
                    }
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }  

    lhc  dalao的分析:https://www.luogu.org/blog/violet2333/hankson-di-qu-wei-ti

    这位dalao证明了一个超棒地结论:https://blog.csdn.net/nuclearsubmarines/article/details/77603154

     


     

    麻球繁衍

    这题必须纪念一下

    各种渠道各种求助dalao,弄了几个小时才明白的


    样例1输入

    3 1 1
    0.33
    0.34
    0.33
    
    

    样例1输出

    0.3300000
    
    

    样例2输入

    3 1 2
    0.33
    0.34
    0.33
    

    样例2输出

    0.4781370


    先说明:

    然后 

     全概率公式

      

     

    好了,全概率公式就补充这些


    下面是该题的做法

    读题知:

    今天的肯定都是昨天新生的,今天这些也肯定到不了明天,今天就死掉了,
    明天的是今天的某些生的,生不生概率是一定的,且每个生的个数是一定的

    今天死光了说明前一天死完了,所以可用前一天死亡的概率就可以来递推今天全部死亡的概率

    询问的是m天内所有生物都死的概率(包括m天前死亡的情况)

    每个麻球都是独立的,而且会在当天死亡,
    每个麻球和它的后代死亡的概率也是独立的

    因为麻球的各种活动都互不影响,所以现在只考虑一只麻球

     再来一遍全概率公式,展开一下: P(A)=P(B1)*P(A|B1)+P(B2)*P(A|B2)…P(Bn)*P(A|Bn)

    因为这j个后代的死亡是独立的,而每个死亡的概率都是f(i-1)(今天死光了说明前一天死完了,所以可用前一天死亡的概率就可以来递推今天全部死亡的概率),

    因此根据乘法公式,j个后代全部死亡的概率为f(i-1)^j 。

    同理,由于一开始共有k只麻球,且各只麻球的死亡是独立的,由乘法公式,最终答案是f(m)^k


    //每只麻球是独立的,k只的答案是一只的k次方。
    //同样,生出的每只麻球也是独立的,单独考虑即可。
    #include<bits/stdc++.h>
    #define N 1000 + 10
    using namespace std;
    
    int n, k, m;
    double p[N], f[N];
    
    int main() {
        scanf("%d %d %d", &n, &k, &m);
        for (int i = 0; i < n; i++) 
            scanf("%lf", &p[i]);
        f[0] = 0, f[1] = p[0];
        for (int i = 2; i <= m; i++) {
            f[i] = 0;
            for (int j = 0; j < n; j++) 
                f[i] += p[j] * pow(f[i - 1], j);
        }
        printf("%.7lf
    ", pow(f[m], k));
        return 0;
    }

    拓展φ 

    样例输入

    11 10

    样例输出

    10
    5
    7
    5
    8
    3
    9
    5
    7
    4
    10

     (嘻嘻嘻,求助了几位dalao才弄懂得,必须要纪念一下)

    这道题就是利用容斥原理啊

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    const int N = 100005;
    int n, prime[N], tot, cnt;
    bool vis[N];
    ll m, num[N], ans;
    
    void getprime() {
        for (int i = 2; i <= n; i++) {
            if (!vis[i])
                prime[++tot] = i;
            for (int j = 1; j <= tot && i * prime[j] <= n; j++) {
                vis[i * prime[j]] = true;
                if (i % prime[j] == 0)
                    break;
            }
        }
    }
    
    void work(int n) {
        for (int i = 1; i <= tot && prime[i] <= n; i++) {
            int x = prime[i];
            if (n % x == 0) {
                num[++cnt] = x;// 
                while (n % x == 0)
                    n /= x;
            }
        }
    }
    
    //减掉与其不互质的,余下的就是互质的个数啦 
    //不互质的咋减呢,找他的质因子喽,同样有这个质因子的肯定跟他不互质啦
    void dfs(int a, int p, int s) {//p约数,s为正负1(加还是减) 
        if (!a) {
            ans += (ll)s * m / p; // m/p是m中p的倍数的个数 
            return;
        }
        //看质因数个数,一个->加,两个->减,三个->加... 
        dfs(a - 1, p, s);
        dfs(a - 1, p * num[a], -1 * s);
        /*比如有因数3,4,5 
                         1
                      /     
                    /         
                   3            1
                 /           /    
               3*4    3      4     1
              /     /     /    / 
          3*4*5 3*4 3*5 3  4*5 4 5   1
        */
    }
    
    signed main() {
        cin >> n >> m;
        getprime();//质数表 
        for (int i = 1; i <= n; i++) {
            ans = 0;
            cnt = 0;//质因子个数 
            work(i);//求i的质因子个数 
            dfs(cnt, 1, 1);
            printf("%lld
    ", ans);
        }
    }
  • 相关阅读:
    为啥我百度定位wifi可以定位准确,但用数据流量就给我定位到非洲西海岸
    利用BottomNavigationBar实现不同的fragment之间的转换
    VS2010中连接sql 2005连接问题microsoft.sqlserver.management.sdk.sfc
    zuul路由网关介绍及使用
    Hystrix断路器概述及使用
    Ribbon负载均衡概述及使用
    Eureka服务注册与发现 介绍及使用
    微服务介绍及springcloud入门概述
    springboot整合springdatajpa步骤及使用
    springboot整合shiro步骤
  • 原文地址:https://www.cnblogs.com/aprincess/p/11822201.html
Copyright © 2020-2023  润新知