容斥学习入门


容斥原理:

容斥原理的实现:

用一个temps[maxn]数组记录各个容斥加减,用-1的连乘进行哈,用a[maxn]数组记录元素的个数;

然后具体的实现算法代码如下:复杂度为O(2^n)

int temp[maxn];
int cnt = 0;
temp[cnt ++] = -1;
for(int i = 0;i < cnt1 ; i ++)//容斥记录所有的情况//cnt1是a[]的大小
{
    int k = cnt;
    for(int j = 0; j < k ; j ++)
    {
        temp[cnt ++] = temp[j] * a[i] * (- 1);
    }
}
ll ans = 0;
for(int i = 1; i < cnt ; i ++)
    ans += temp[i];
return ans;



Co-Prime


题意:求在区间[ x , y ]有多少数与n 互质;

思路:将n拆分成质因数,然后在[x,,y]这个区间的找到能被这些质因数整除的数,用在这个区间的数的个数减去能被这些质因数整除的数的个数。

因为各个素数对应的数有可能重合,所以这里就要用到容斥原理;

可以先求【1,y】,【1,x - 1】对应的个数,之后前者减去后者;因为这里考虑到了个数,容斥进行的是他们对应的公倍数,然后用区间长度除一下这个公倍数就对应的是对应的个数了;


#include<bits/stdc++.h>
using namespace std;
const int maxn = 10000+ 10;
typedef long long ll;
int a[maxn];//记录的是n的质因子
ll temp[maxn*10];//记录的容斥的元素

int Init(ll n)//得出n的质因子数组
{
    int num = 0;
    for(int i = 2; i * i <= n ; i ++)
    {
        if(n % i == 0)
        {
            a[num ++] = i;
            while(n % i == 0)
            {
                n = n / i;
            }
        }
    }
    if(n > 1)//剩下的是质数了
    {
        a[num ++] = n;
    }
    return num;
}
ll Eclusion(ll m,ll n)
{
    memset(a,0,sizeof(a));
    memset(temp,0,sizeof(temp));
    int num = Init(n);
    int len = 0;
    temp[len ++] = -1;
    for(int i = 0;i < num ; i ++)//容斥记录所有的情况
    {
        int k = len;
        for(int j = 0; j < k ; j ++)
        {
            temp[len ++] = temp[j] * a[i] * (- 1);
        }
    }//temp数组记录的容斥后的各个带符号的公倍数
    ll ans = 0;
    for(int i = 1; i < len ; i ++)
    {
        ans += m/temp[i];
    }
    return ans;//ans记录的是不符合与n互质的数的个数

}

int main()
{
    int Tcase;
    scanf("%d",&Tcase);
    for(int ii = 1; ii <= Tcase ; ii ++)
    {
        ll x,y,n;
        scanf("%I64d%I64d%I64d",&x,&y,&n);
        ll ans = (y - Eclusion(y,n)) - (x - 1 - Eclusion(x - 1,n));
        cout <<"Case #"<< ii << ": "<< ans << endl;
    }
    return 0;
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值