大致思路就是先求出n的质因数假设是a1-an,然后在1-a的区间里面查找至少能整除{a1,a2...an}中一个元素的数有多少个,对1-b也做相同的处理,而找出来的元素肯定是与n不互质的,那么把区间的长度减去元素的个数就是那个区间里面与n互质的数的个数了,然后1-b的减去1-(a-1)的就是答案了。

而在1-a的区间里面查找至少能整除{a1,a2...an}中一个元素的数有多少个,这里就要用到容斥原理了。

首先来看容斥原理

计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。

就比如质因数有2,3 然后1-10里面能整除2的有2,4,6,8,10;能整除3的有3,6,9;把这个看作成集合A,集合B,|A∩B|=1,|A|=5,|B|=3,|A∪B|=|A|+|B|-|A∩B|;

将这个公式推广到n个集合南理第八届校赛同步赛-C count_prime//容斥原理

回到题目,考虑质因子{a1,a2,a3..an},那么在[1-r]有多少个数能整除ai,答案就是[r/ai],但是单纯的把答案加上去肯定是错的(有些数可能被好几个质因子整除),这个时候就用到容斥原理来解决。

假设有m个质因子,那么就有2^m-1种情况(lcm(...),中间填入数字,每个数字都有两种选择,填还是不填,但不能全部都不填对吧);

附上模板

int solve (ll n, ll r)
{

        vector<ll> p;
        p.clear();
        for (int i=2; i*i<=n; ++i)
                if (n % i == 0)
                {
                    p.push_back (i);
               while (n % i == 0)
                    n /= i;
                }
               if (n > 1)
                p.push_back (n);
        //分解质因数
        ll sum = 0;
        ll cur;
        ll mult = 1;
        ll bits = 0;
        ll s=1<<p.size();
        for (ll msk=1; msk<s; msk++)
        {

              mult = 1;
               bits = 0;
                for (int i=0; i<p.size(); ++i)
                        if (msk & (1<<i))
                        {
                                bits++;
                               mult *= p[i];

                       }
               cur = r / mult;
                if (bits % 2 == 1)
                sum += cur;
               else
                sum -= cur;

        }
        //printf("%lld\n",sum);
        return r - sum;//1-r与n互质的数的个数

}
View Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-17
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-11-06
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案