容斥原理專題
阿新 • • 發佈:2020-08-24
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;
}