1. 程式人生 > 實用技巧 >容斥原理專題

容斥原理專題

hdoj1796

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
const int N=20+10;
int n,m;
int a[20];
int gcd(int x,int y){
    return x%y?gcd(y,x%y):y;
}
signed main(){
    int T,x,y;
    while (scanf("%lld%lld",&n,&m)==2){
        n--;
        for (int i=0;i<m;i++){
            scanf("%lld",&a[i]);
            if (a[i]==0)i--,m--;
        }
        int ans=0;
        for (int i=1;i<(1<<m);i++){
            int p=1,cnt=0;
            for (int j=0;j<m;j++){
                if ((1<<j)&i){
                    p*=a[j]/gcd(p,a[j]);
                    cnt++;
                }
            }
            if (cnt&1)ans+=n/p;
            else ans-=n/p;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

hdoj2204

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
const int N=70+10;
int n,m;
int vis[N],prim[N];	
void euler(int n){
    int num=0;
    for (int i=2;i<=n;i++){
        if (vis[i]==0)prim[++num]=i;
        for (int j=1;j<=num&&prim[j]*i<=n;j++){
            vis[i*prim[j]]=1; 
            if (i%prim[j]==0)break;
        }
    }
}
int ans;
void dfs(int pre,int num,int cnt){
    for(int i=pre;;i++){
        int p=pow(n,1.0/num/prim[i])-1;
        if (!p)break;
        if (cnt&1)ans+=p;
        else ans-=p;
        dfs(i+1,num*prim[i],cnt+1);
    }
}
signed main(){
    int T,x,y;
    euler(70);
    while (scanf("%lld",&n)==1){
        ans=1;
        dfs(1,1,1);
        printf("%lld\n",ans);
    }
    return 0;
}

hdoj3388

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int ll
const int N=70+10;
int n,m,cnt;
int a[N];
int ans;
void dfs(int k,int num,int s,int n){
    if (k==cnt+1){
        if (num&1)ans-=n/s;
        else ans+=n/s;//當num為0時為整體
        return;
    }
    dfs(k+1,num,s,n);
    dfs(k+1,num+1,s*a[k],n);
}
signed main(){
    int T,x,y,k;
    scanf("%lld",&T);
    for (int cas=1;cas<=T;cas++){
        scanf("%lld%lld%lld",&x,&y,&k);
        cnt=0;
        int t=max(x,y);
        for (int i=2;i*i<=t;i++){
            if (x%i==0||y%i==0)a[++cnt]=i;
            while (x%i==0)x/=i;
            while (y%i==0)y/=i;
        }
        if (x>1)a[++cnt]=x;if (y>1&&x!=y)a[++cnt]=y;
        int l=1,r=1e16;
        while (l<=r){
            int mid=(l+r)>>1;
            ans=0;
            dfs(1,0,1,mid);
            if (ans<k)l=mid+1;
            else r=mid-1;
        }
        printf("Case %lld: %lld\n",cas,l);
    }
    return 0;
}

hdoj1695

x a~b,y c~d gcd(x,y)=k的個數,因為(1,5)(5,1)被認為相同,所以要去重,注意(k,k)只有1組或0組

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=1e6+10;
int n,m,k;
int mu[N],vis[N],prim[N],sum[N];
void get_mu(int n){
    int cnt=0; 
    mu[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i]){prim[++cnt]=i;mu[i]=-1;}
        for(int j=1;j<=cnt&&prim[j]*i<=n;j++){
            vis[prim[j]*i]=1;
            if(i%prim[j]==0)break;
            else mu[i*prim[j]]=-mu[i];
        }
    }
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+mu[i];
}
ll S(int n,int m){
    n/=k;m/=k;
    if (n>m)swap(n,m);
    ll ans1=0,ans2=0;
    for(int l=1,r;l<=n;l=r+1){
        r=min(n/(n/l),m/(m/l));
        ans1+=1ll*(sum[r]-sum[l-1])*(n/l)*(m/l);
    }
    for(int l=1,r;l<=n;l=r+1){
        r=n/(n/l);
        ans2+=1ll*(sum[r]-sum[l-1])*(n/l)*(n/l);
    }
    return ans1-ans2/2;
}
int main(){
    int T,a,b,c,d;
    get_mu(N-1);
    scanf("%d",&T);
    for (int cas=1;cas<=T;cas++){
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        if (k==0){
            printf("Case %d: 0\n",cas);
            continue;
        }
        printf("Case %d: %lld\n",cas,S(b,d)+S(a-1,c-1)-S(a-1,d)-S(b,c-1));
    }
    return 0;
}

hdoj4135

hdoj5514

hdoj5201

hdoj5297

hdoj6021

hdoj5155

hdoj5471

hdoj2841

hdoj5794

hdoj6053

hdoj5468

hdoj4790