Longge's problem

Longge's problem

来自:POJ2480

欧拉函数算法:

#include <iostream>
#include <ctime>
using namespace std;
#define LL long long
//这题的数据极大,因此一定要保证各个地方都是大于int的整型数字
LL eular(LL n){
    LL res=n;
    for(LL i=2;i*i<=n;i++){ //n^0.5
        if(n<i) break;
        if(n%i==0){
            res=res/i*(i-1);    //欧拉函数的计算
            while(n%i==0)   //将质因数除尽达到筛选质数的效果
                n/=i;   //logn  <!-1
        }
    }
    if(n>1) res=res/n*(n-1);    //大于根号N的质因数最多只有一个
    return res;
}

int main(){
    LL a;
    while(cin>>a){
        clock_t beg=clock();
        LL ret=eular(a)+a;
        for(LL i=2;i*i<=a;i++){     //<!-2
            if(a%i==0){     //枚举因数
                if(i*i==a) ret+=i*eular(a/i);     //恰好平方根
                else
                    ret+=i*eular(a/i)+(a/i)*eular(i);   //大小因数都要算进去
            }
        }
        clock_t end=clock();
        cout<<ret<<" in time:"<<end-beg<<"ms"<<endl;
    }
    return 0;
}

参考了大佬的博客后才大概弄懂其中的原理,自己一开始根本不懂什么欧拉函数、积性函数,对这题也没什么很好的思路,主要需要解决的问题就是最大公约数的得出,因数自然是本身,质数是1,但其他非质数可能与n互质也可能有某个最大公约数d,而这个d的计算单独来看似乎没什么很好的办法(至少我的数论水平让我莫得任何想法)。因此利用了欧拉函数 phi(n) 的值是小于n的正整数中与n互质的数的个数,而这些数与n的最大公因数显然是1,而n本身是n与n的最大公因数,解决了这两类数,还剩下与n不互质的部分,设其中某个数为i,那么假设有 gcd(i,n)=d ,同除以d后有 gcd(i/d,n/d)=1 ,显然 phi(n/d) 的值就是这种情况的个数,设为j,那么最大公因数为d的情况有j种,逐个枚举因数计算 phi(n/d)*j 并求和,加上另外两类数的和即可得到最终结果。

尽管如此,对于问题的分析过程还是让我受益良多,具体问题具体分析在这里体现的很好,抓住问题的特征归纳总结,发现将n和i都除以d后就可以转化为共性问题用欧拉函数求解,直接计算出其结果来避免穷举,提高求解效率。

另外本程序的时间复杂度我不知道该如何计算,<!-1 处应该是 logn ,但 <!-2 处因为只有因数才有后续计算导致时间复杂度并非 n^0.5 ,而是远小于乃至接近一个常数,这可能要考虑因数的分布才能得出结论。

欧基米德算法:

#include <iostream>
#include <ctime>
using namespace std;
#define LL long long
//这题的数据极大,因此一定要保证各个地方都是大于int的整型数字
LL euclid(LL n,LL m){   //辗转相除法
    while(n%m!=0){  //logn
        LL t=m;
        m=n%m;
        n=t;
    }
    return m;
}

int main(){
    LL a;
    while(cin>>a){
        clock_t beg=clock();
        LL ret=1;
        for(LL i=2;i<=a;i++){   //n
            if(a%i==0) ret+=i;
            else ret+=euclid(a,i);
        }
        clock_t end=clock();
        cout<<ret<<" in time:"<<end-beg<<"ms"<<endl;
    }
    return 0;
}

辗转相除部分课程资料里显示复杂度为 O(logn) ,也不知道是怎么得出来的,时间复杂度是 O(nlogn) ,效率被欧拉函数算法甩了好几条街,不过也可以理解,毕竟就是个爆破穷举。

参考:[

欧拉函数

浅谈欧拉函数(Eular)

]

posted @   Festu  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示