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;
}
posted @ 2012-01-03 12:31  Because Of You  Views(1639)  Comments(0Edit  收藏  举报