1. 程式人生 > >HDU 4135 容斥定理 分解質因數

HDU 4135 容斥定理 分解質因數

題意:給定一段區間內求與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;
}