hdu 1695 hdu 4135 容斥原理求1-n 区间内与r互质的个数

方法:

先对n分解质因数,分别记录每个质因数,那么所求区间内与某个质因数不互质的个数就是n / r(i),假设r(i)是r的某个质因子。

假设只有三个质因子,总的不互质的个数应该为p1+p2+p3-p1*p2-p1*p3-p2*p3+p1*p2*p3,及容斥原理,可以转向百度百科查看相关内容

pi代表n/r(i),即与某个质因子不互质的数的个数

当有更多个质因子的时候,可以用状态压缩解决,二进制位上是1表示这个质因子被取进去了。如果有奇数个1,就相加,反之则相减

View Code
#include<vector>
#include<cstdio>
using namespace std;
__int64 solve(int r,__int64 n){
vector<int> p;
int i;
for(i=2;i*i<=r;i++){
if(r%i==0){
p.push_back(i);
while(r%i==0){
r/=i;
}
}
}
if(r>1) p.push_back(r);
__int64 sum=0;
for(int num=1;num<(1<<p.size());num++){
__int64 mult=1,ones=0;
for(i=0;i<p.size();i++){
if(num&(1<<i)){
ones++;
mult*=p[i];
}
}
if(ones%2) sum+=n/mult;
else sum-=n/mult;
}
return n-sum;
}
int main(){
int t,c;
__int64 a,b;
__int64 cases=1;
scanf("%d",&t);
while(t--){
scanf("%I64d%I64d%d",&a,&b,&c);
printf("Case #%I64d: %I64d\n",cases++,solve(c,b)-solve(c,a-1));
}
return 0;
}


hdu 1695 

View Code
#include<vector>

#include<cstdio>

using namespace std;

int prm[50000];

int tot=0;

bool flag[100010];

void init()

{

    int i,j;

    memset(flag,false,sizeof(flag));

    for(i=2;i<=100000;i++)

    {

        for(j=2*i;j<=100000;j+=i)

        {

            flag[j]=true;

        }

    }

    for(i=2;i<=100000;i++)

    {

        if(!flag[i])

            prm[++tot]=i;

    }

}

__int64 solve(int r,__int64 n){

    int p[50];

    int cnt=0;

    int i;

    if(!flag[r])

    {

        if(r>1)

            p[cnt++]=r;

    }

    else 

    {

        for(i=1;i<=tot;i++)

        {

            if(r%prm[i]==0)

            {

                p[cnt++]=prm[i];

                while(r%prm[i]==0)        r/=prm[i];

                if(!flag[r])

                {

                    if(r>1)

                    {

                        p[cnt++]=r;r=1;

                    }

                    break;

                }

            }

        }if(r>1) p[cnt++]=r;

    }

    __int64 sum=0;

    for(int num=1;num<(1<<cnt);num++){

        __int64 mult=1,ones=0;

        for(i=0;i<cnt;i++){

            if(num&(1<<i)){

                ones++;

                mult*=p[i];

            }

        }

        if(ones%2) sum+=n/mult;

        else sum-=n/mult;

    }

    return n-sum;

}

int main(){

    int t;

    init();

    __int64 a,b,c,d,e;

    __int64 cases=1;

    scanf("%d",&t);

    while(t--){

        scanf("%I64d%I64d%I64d%I64d%I64d",&a,&b,&c,&d,&e);

        if(e==0||b<e||d<e) 

        {

            printf("Case %I64d: 0\n",cases++);

            continue;

        }

         a = b < d ? b : d;

                 b = b > d ? b : d;

                 a /= e;

                 b /= e;

        __int64 ans=0;

        for(int i=1;i<=a;i++)

        {

            if(i>1)

            ans+=solve(i,b)-solve(i,i-1);

            else ans+=b;

        }

        printf("Case %I64d: %I64d\n",cases++,ans);

    }

    return 0;

}

你可能感兴趣的:(HDU)