求逆欧拉函数(arc)

已知欧拉函数计算公式

  初始公式:φ(n)=n*(1-1/p1)*(1-1/p2).....*(1-1/pm)

     又 n=p1^a1*p2^a2*...*ps^as  欧拉函数是积性函数

  那么:φ(n)=φ(p1^a1)* φ(p2^a2)........φ(pn^an).

  

  

复制代码
#include<cstdio>
#include<ctime>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#define LL long long
#define maxn 100010
#define MAXN 10000000
using namespace std;
LL n,k,prime[MAXN/10],cnt,ans[maxn];
bool mark[MAXN+10];
void first()
{
    for(int i=2;i<=MAXN;i++)
    {
        if(!mark[i])    prime[++cnt]=i;
        for(int j=1;j<=cnt;j++)
        {
            if(i*prime[j]>MAXN) break;
            mark[i*prime[j]]=1;
            if(i%prime[j] ==0) break;
        }
    }
    return ;
}
LL mul(LL a,LL b,LL mod)
{
    LL ans=0;
    while(b)
    {
        if(b&1)    ans=(ans+a)%mod;
        a=(a<<1)%mod;b>>=1;        
    }
    return ans;
}
LL low(LL a,LL b,LL mod)
{
    LL ans=1;
    while(b)
    {
        if(b&1)    ans=mul(ans,a,mod);
        b>>=1,a=mul(a,a,mod);
    }
    return ans;
}
bool Is_prime(LL n)
{
    if(n<2)    return 0;
    if(n==2)    return 1;
    if(n%2 ==0) return 0;
    LL m=n-1,j=0;
    while(m%2 == 0)
    {
        j++;
        m>>=1;
    }
    for(int i=1;i<=5;i++)
    {
        LL a=rand()%(n-1)+1;
        LL x=low(a,m,n);
        LL y;
        for(int k=1;k<=j;k++)
        {
            y=mul(x,x,n);
            if(y==1&&x!=1&&x!=n-1 )
                return 0;
            x=y;
        }
        if(x!=1) return 0;
    }
    return 1;
}
void dfs(LL x,LL y,LL mod )
{
    if(x==1)
    {
        ans[++ans[0]]=y;
        return ;
    }
    if(x+1 > prime[cnt] && Is_prime(x+1))
        ans[++ans[0]]=y*(x+1);
    for(int i=mod;i>=1;i--)
    if(x%(prime[i]-1) == 0)
    {
        LL a=x/(prime[i]-1),b=y,c=1;
        while(a%c ==0)
        {
            b*=prime[i];
            dfs(a/c,b,i-1);
            c*=prime[i];
        }
    }
}
int main()
{
    freopen("arc.in","r",stdin);
    freopen("arc.out","w",stdout);
    scanf("%lld%lld",&n,&k);
    srand(time(0));
    first();
    dfs(n,1,cnt);
    sort(ans+1,ans+1+ans[0]);
    for(int i=1;i<=k;i++)
        printf("%lld ",ans[i]);
    return 0;
}
复制代码

 

posted @   浪矢-CL  阅读(1226)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示