• 数论部分补题的一点小收获


        连续5天的数学部分的知识学习已经结束了,今天本该好好消化吸收前4天所讲的知识点,最终却睡了一下午玩了一晚上。。。翻了翻早上半天时间补题的记录,还是总结一点东西吧,大部分还是昨天的研究成果。

        

        首先是K题:POJ 1284 Primitive Roots  题意很好理解,就是给定一个奇素数p,求它的原根个数。

         看懂了原根的定义以后,开始以为要一个一个检验计数,觉得太麻烦了,当然这个坑待填(求奇素数的最小原根)。这里讲清楚了原根个数的计算公式:一个整数m的原根个数为phi(phi(m))。特别地,p为素数时,phi(p)=p-1,那么p的原根个数就是phi(p-1)。那么这题就完结了。

        接下来说I题:POJ 3641 Pseudoprime numbers 伪素数——以我理解就是满足费马小定理的非素数。

        在维基百科欧拉函数的词条刚好看到了费马小定理的表述,这里先讲是因为昨天做这题刚好用错过。

        

        贴上部分代码说明:

    bool isPrime(ll x)
    {  // 判断是否时素数,配合素数打表使用
        if(x<=40000)  return !notprime[x];
        for(int i=0;i<cnt && primes[i]<=x/primes[i];i++)
        {
            if(x%primes[i]==0)
                return false;
        }
        return true;
    }
    
    ll pow_mod(ll a, ll n, ll mod)
    {  // 快速幂取模
        ll ans = 1;
        a %= mod;
        while(n>0)
        {
            if(n&1)
            {
                ans *= a;
                ans %= mod;
            }
            a *= a%mod;
            a %= mod;
            n >>= 1;
        }
        return ans;
    
    }
    
    int main()
    {  
        prime_table(40000);
    
        ll p, a;
        while(scanf("%lld %lld", &p, &a)!=EOF && a)
        {
            if(!isPrime(p) && pow_mod(a, p, p)==a%p)    //  WA : a^(p-1) == 1
                printf("yes
    ");
            else
                printf("no
    ");
        }
    
        return 0;
    }

       由于a为正整数,gcd(a,p)不一定为1,所以利用费马小定理应该判断a^p%p是否等于a%p,而不是 a^(p-1)%p==1,我少算了1次幂以为能省时间反倒让我debug了好久。。。

        H题:POJ 3421 X-factor Chains 理解了题目意思后问题不大,很容易得到最长的X-链长度(素因子个数),就是被样例的数据误导了,走了些弯路探索排列总数有多少,其实就是简单的排列数问题。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    int primes[1100001], cnt;
    bool notprime[1100001];
    
    void prime_table(int n)
    {
        notprime[0] = notprime[1] = 1;
        for(int i=2;i<=n;i++)
        {
            if(!notprime[i])  
                primes[cnt++] = i;
    
            for(int j=0;j<cnt && i<=n/primes[j];j++)
            {
                notprime[i*primes[j]] = 1;
                if(i%primes[j] == 0) 
                    break;
            }
        }
    }
    
    long long fact(int n)
    {
        if(n==1||n==0)  return 1;
        return fact(n-1)*n;
    }
    
    long long res;
    int diver(int n)
    {
        int ans = 0;
        for(int i=0;i<cnt && n>=primes[i];i++)
        {
            if(!notprime[n])
            {
                ans++;
                break;
            }
            int t = 0;
            while(n%primes[i]==0)
            {
                n /= primes[i];
                t++;
            }
            res *= fact(t); 
            ans += t;
    
        }
        return ans;
    } 
    
    int main()
    {
        prime_table(1100000);
        int x;
        while(scanf("%d", &x)!=EOF)
        {
            res = 1;
            int maxlen = diver(x);
            printf("%d %lld
    ", maxlen, fact(maxlen)/res);
        }
    }
    View Code

        最后时G题:POJ 3292 Semi-prime H-numbers

        自己改造素数表的筛法经历了各种TLE和WA,参考了别人的代码才解决,折叠吧。大佬的代码在筛选的时候就标注了H-numbers的三种类型:prime/semi-prime/非semi-prime,避免了像我开始那样找到了筛选了全部的prime表后再次两两相乘组合,然后再将结果排序,最后线性查找给定的h前面有多少semi-prime。。。真是一把辛酸泪

    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    const int maxn = 1000001;
    int H[maxn+1], sum[maxn+1];
    void solve()
    {  // 类似筛法得到素数表
        for(int i=5;i<=maxn;i+=4)
            for(int j=5;j<=maxn && j<=maxn/i;j+=4)
            {  // H[i]==0 表示 i为H-prime
    
                if(!H[i]&&!H[j])
                    H[i*j] = 1;  //标记是semi-prime
                else
                    H[i*j] = -1;  //非semi-prime的合数
    
            }
    
        int cnt = 0;
        for(int i=1;i<=maxn;i++)
        {
            if(H[i]==1)  cnt++;
            sum[i] = cnt;
        }
    }
    
    int main()
    {  
        solve();
        int h;
        while(scanf("%d", &h)!=EOF && h)
        {
            printf("%d %d
    ", c, sum[h]);
        }
    
        return 0;
    }
    View Code

        今天还有好多知识点还没消化完,博客开始也一点不想记录,想了半天感觉一无所获0.0 所以标题还是夸大了点Orz

        最后还是提醒自己有空研究以下概念阶梯博弈莫比乌斯反演,然和利用莫比乌斯反演以及第一天PPT上所讲解决P题:HDU 5663 Hillan and the girl

        

        END.

  • 相关阅读:
    Linux关闭jetty服务器脚本
    TreeMap 源码解读
    LinkedHashMap 源码解读
    HashTable 源码解读
    MappedByteBuffer文件句柄释放问题
    HashMap源码解读
    Java 对象创建过程
    java 虚拟机内存介绍
    dubbo 部署
    kotlin 学习入门
  • 原文地址:https://www.cnblogs.com/izcat/p/9428131.html
Copyright © 2020-2023  润新知