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

来源:互联网 发布:nba步行者特纳体测数据 编辑:程序博客网 时间:2024/06/03 20:53

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

AC Code

/** @Cain*/vector<ll >v;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<<v.size());i++){ //二进制枚举所有可能        ll tmp = 1,cnt = 0;        for(ll j = 0;j<v.size();j++){        //我们不仅要知道该个二进制有多少位1,并且还要具体知道是在        //哪一位上有1. 这样我们才可以知道当前枚举了哪些质因子.        //所以这个枚举的姿势要选好.!!!             if(i&(1<<j)){             //记住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));}