容斥原理求解1~r中和某个数m互质的数的个数

百度百科有一道例题就是用容斥原理计算这个的,如果不明白的可以先看看那个。
我们首先要利用容斥原理求得和m不互质的数,为此我们先找出m的素因子

void get_fac(ll m)   //要找的m的素因子
{
    for(ll i=2;i*i<=m;i++)
    {
        if(m%i==0)
        {
            fac[cnt++]=i;   //fac存素因子,cnt从0开始
            while(m%i==0)  //保证后面的数是m的素因子
                m/=i;
        }
    }
    if(m>1)
        fac[cnt++]=m;
}

如果一个数有m的素因子,那么他就一定不和m互质,比如30的素因子有2,3,5,那么所有2的倍数就不和30互质,同理3的倍数,5的倍数也不和30互质,这里假设要求1~30内和30互质的数,那么r=30.设X1是2在1到30中2的倍数的个数,则X1=15,同理对3,X2=10,对5,X3=6,对23,X4=5 ;对2 * 5,X5=3;对3 * 5,X6=2;对23*5,X7=1,所以和30不互质的数就有X1+X2+X3-(X4+X5+X6)+X7=22个,则与30互质的数就有8个,和30的欧拉函数值相等.
程序写法:
1.dfs():在递归的每一层都决策一下这个数选不选,第几层就是第几个数.

void dfs(int pos,int use,int cur,int up)
{
    if(pos==cnt)   //有一条一个数都没用
    {
        if(use == 0)
            return ;
        if(use&1)
            sum+=up/cur;  //sum保存和m不互质的数的个数
        else
            sum-=up/cur;
        return ;
    }
    dfs(pos+1,use+1,cur*fac[pos],up);
    dfs(pos+1,use,cur,up);
}

//调用形式:dfs(0,0,1,r);  //(递归层数,用了的数的数量,1保存每一项(即X1或X2..)的值,上限范围);

2.位运算

ll Find(ll up)   //up表示上限
{
    if(n==1) return up;  //1和任意数互质
    if(up==1)  return 1;   //上限是1就是只有一个数
    ll res=0;
    for(ll i=1;i<(1<<cnt);i++)  //i的二进制表示用了哪几个数,比如i=3,二进制为011就表示用了第一个数和第二个数,i=4就表示用了第三个数
    {
        ll p=1,coun=0;
        for(ll j=1;j<=cnt;j++)
        {
            if(i&(1<<(j-1)))
            {
                p*=fac[j];
                coun++;
            }
        }
        res+=(coun%2)?up/p:(-up/p);
    }
    return up-res;   //res为和m不互质的数的个数,那么up-res就是互质的数的个数
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值