HDU - 4135 Co-prime(容斥原理)
題目鏈接:點擊查看
題目大意:給出一個區間[l,r],再給出一個n,問區間中有多少個數與n互質
題目分析:容斥原理應用的經典題目,馬克一篇非常不錯的博客,留著以后慢慢消化:
https://blog.csdn.net/m0_37286282/article/details/78869512
那么這個題目轉換一下,先求1~m中有多少個與n互質的數,這樣cal(r)-cal(l-1)就是答案了
舉個很簡單的例子應該就能懂了:
若要求1~8中有多少個與12互質的數,正難則反,我們先求一下1~8中有多少個與12不互質的數,最后用區間中的總數減去不互質的數就是答案了,那么首先將12進行唯一分解,分解得到了兩個質因子分別是2和3,那么在區間中與12不互斥的數一定能被2或3整除才行,也就是說現在需要求8中有多少個數能被2和3整除,能被2整除的數有8/2=4個,同理能被3整除的數有8/3=2個,但答案真的是2+4=6個嗎?我們枚舉出來數一下,發現符合我們需要的數只有2,3,4,6,8五個數,算出來的答案是因為將6重復計算了兩次,所以我們需要利用容斥原理減去重復的,也就是8/(2*3)=1個,得到的答案為5,這個答案是1~8中與12不互質的數,所以最終答案就是8-5=3了
根據上面一個簡單的例子,我們可以將容斥原理推廣一下,對于每個集合,我們可以奇加偶減,因為對于一個小于1e9的數,唯一分解后的素因子不超過10個,故我們可以用一個2^k的算法枚舉子集,dfs或狀壓都可以,計算出與n不互質的答案后,最終用m減去這個答案就能得到最終答案了
代碼:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=210;vector<int>fact;LL solve(LL n,LL m) {fact.clear();for(LL i=2;i*i<=n;i++){if(n%i==0){fact.push_back(i);while(n%i==0)n/=i;}}if(n>1)fact.push_back(n);LL ans=0;for(int i=1;i<(1<<fact.size());i++){LL cnt=0;LL mul=1;for(int j=0;j<fact.size();j++){if(i&(1<<j)){cnt++;mul*=fact[j];}}if(cnt&1)//奇加偶減 ans+=m/mul;elseans-=m/mul;}return m-ans; }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int w;cin>>w;int kase=0;while(w--){LL l,r,n;scanf("%lld%lld%lld",&l,&r,&n);printf("Case #%d: %lld\n",++kase,solve(n,r)-solve(n,l-1));}return 0; }?
總結
以上是生活随笔為你收集整理的HDU - 4135 Co-prime(容斥原理)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 洛谷 - P3358 最长k可重区间集问
- 下一篇: POJ - 1091 跳蚤(容斥原理+数