HDU 4135 容斥定理 分解質因數
阿新 • • 發佈:2018-12-11
題意:給定一段區間內求與n互質的個數
由於尤拉函式有侷限性,所以可以用容斥做;
如果單純的解一段區間很難,所以我們可以從反面來做要求的
【a,b】=【1,b】-【1,a-1】
下面說下怎麼容斥:
比如一段區間【1,30】另外給定一個n=10
1.分解n的素因子 2和5
2.用二進位制容斥模板: 結果=30-(30/2+30/5-30/10 (注意這裡是最小公倍數) )
程式碼:
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <vector> #include <cstdio> #include <cmath> #include <queue> #include <set> #include <map> using namespace std; typedef long long ll; const ll N=100010; const ll INF=0xfffffff; const ll mod=1e9+7; #define loop0(i,a,n) for(ll i=a;i<n;i++) #define loop1(i,a,n) for(ll i=a;i<=n;i++) #define loop11(i,a,n) for(ll i=a;i*i<=n;i++) #define reloop0(i,a,n) for(ll i=n-1;i>=a;i++) ll fac[50]; ll solve(ll n,ll m) { ll result=0,numbers=0; loop11(i,2,n) { if(n%i==0) { fac[numbers++]=i; while(n%i==0)n=n/i; } } if(n!=1)fac[numbers++]=n; loop0(i,1,1<<numbers) { ll count=0,sum=1; loop0(j,0,numbers)if(i&(1<<j))count++,sum=sum*fac[j]; if(count&1)result+=m/sum; else result-=m/sum; } return m-result; } int main() { ll t,a,b,n,cas=0; cin>>t; while(t--) { cin>>a>>b>>n; printf("Case #%lld: ",++cas); ll result=solve(n,b)-solve(n,a-1); cout<<result<<endl; } return 0; }