HDU -- 4135 Co-prime【质因子分解+状压 + 容斥定理】+ 模板

传送门
//问l,r中和n互质的数有几个. 即gcd(n,k) == 1的有多少个元素.
//思路 : 分解n的质因子, 然后用容斥定理算每一区间中可以整除这个质因子的有几个.

AC Code

/** @Cain*/
vectorv;
ll rongchi(ll x,ll n)   //就算1-x中与n互素的数的个数.
{
    v.clear();
    for(ll i=2;i*i<=n;i++){
        if( n%i == 0){
            while( n%i == 0) n /= i;
            v.push_back(i);
        }
    }
    if( n != 1) v.push_back(n);

     //用二进制来1,0来表示第几个素因子是否被用到,如size=3, 三个因子是2,3,5
     //则i=3时二进制是011, 表示第2,3个因子被用到,类似状态压缩.
     //size最大10左右. 枚举出所有的因子可能的组合性.
    ll sum = 0;
    for(ll i=1;i<(1<//二进制枚举所有可能
        ll tmp = 1,cnt = 0;
        for(ll j = 0;j//我们不仅要知道该个二进制有多少位1,并且还要具体知道是在
        //哪一位上有1. 这样我们才可以知道当前枚举了哪些质因子.
        //所以这个枚举的姿势要选好.!!! 
            if(i&(1<//记住j里面始终都只有一个1.这样我们不仅可以知道当前的i有多少
        //为1,并且具体是在那些位上.
                tmp *= v[j];
                cnt++;
            }
        }
        if(cnt%2) sum += x/tmp;  //容斥原理,奇加偶减
        else sum -= x/tmp;
    }
    return x-sum;  //最后返回区间长度-不满足的数.
}

void solve()
{
    ll l,r,n;
    scanf("%lld%lld%lld",&l,&r,&n);
    printf("Case #%d: ",cas++);
    printf("%lld\n",rongchi(r,n) - rongchi(l-1,n));
}

你可能感兴趣的:(容斥定理)