介绍
Co-prime HDU - 4135
用位运算生成所有可能
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=1e3+5;
ll a,b,n;
int num;
ll fac[N];
void factor()
{
ll tn=n;
num=0;
for(ll i=2;i*i<=n;i++)
{
if(tn%i==0)
{
fac[num++]=i;
while(tn%i==0)
tn/=i;
}
}
if(tn>1)
fac[num++]=tn;
}
ll solve(ll x)
{
ll ans=0;
for(int i=1;i<(1<<num);i++)//(1)
{
ll res=1;
int cnt=0;
for(int j=0;j<num;j++)//遍历n所有的素因子
{
if(i&(1<<j))//(2)
{
cnt++;
res*=fac[j];
}
}
if(cnt&1)
ans+=(x/res);
else
ans-=(x/res);
}
return ans;
}
int main()
{
int t,cas=0;
scanf("%d",&t);
while(t--)
{
scanf("%lld%lld%lld",&a,&b,&n);
factor();
printf("Case #%d: %lld\n",++cas,b-a+1-solve(b)+solve(a-1));
}
return 0;
}
(1):因为组合数的表示:
C(k,0)+C(k,1)+…+C(k,k)=2^k
又因为题目中,至少要取1个数,所以用<,一个数表示一个可能情况。
(2)
对取得每种情况进行分析,
取一定数目的数时,对应了多个i,而对于每个i,通过这个操作刚好可以求出此时i对应的是所选择的哪几个数,而且不重复。(神奇之处)