容斥原理专题
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
n~m内与k互质的数的个数
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=30+10;
ll n,m;
int k,cnt;
int prim[N];
ll calc(ll n){
ll ans=0;
for(int i=1;i<(1<<cnt);i++){
int tmp=1,r=0;
for(int j=0;j<cnt;j++){
if(((i>>j)&1)==0)continue;
r++;tmp*=prim[j];
}
if(r&1)ans+=n/tmp;
else ans-=n/tmp;
}
return n-ans;
}
int main(){
int T,a,b,c,d;
scanf("%d",&T);
for (int cas=1;cas<=T;cas++){
scanf("%lld%lld%d",&n,&m,&k);
cnt=0;
for (int i=2;i*i<=k;i++){
if (k%i==0)prim[cnt++]=i;
while (k%i==0)k/=i;
}
if (k>1)prim[cnt++]=k;
printf("Case #%d: %lld\n",cas,calc(m)-calc(n-1));
}
return 0;
}
hdoj5514
有n青蛙,m个绕成圈的台阶,0-m-1,每个青蛙有跳的距离,问能被跳到的台阶的下标和
法1:1-n与n互质的数的和为phi(n)*n/2
对于步长为x的求和来说,就是x∗(与m/x互素的数的和),然后枚举所有的可能的步长,求和
法2:容斥
详见https://blog.csdn.net/qingshui23/article/details/73091006
//法1
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=1e4+10;
int n,m;
int a[N],p[N],vis[N],num[N];
int euler(int n){
int ret=n;
for(int i=2;i<=sqrt(n);i++){
if(n%i==0){
ret=ret/i*(i-1);
while(n%i==0)n/=i;
}
}
if(n>1)ret=ret/n*(n-1);
return ret;
}
int gcd(int x,int y){
return x%y?gcd(y,x%y):y;
}
int ck(int x){
for(int i=1;i<=n;i++)
if(x%a[i]==0)return 1;
return 0;
}
signed main(){
int T;
scanf("%d",&T);
for (int cas=1;cas<=T;cas++){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]=gcd(a[i],m);
}
ll ans=0;
for (int i=1;i*i<=m;i++){
if(m%i)continue;
if (ck(i))ans+=(1ll*euler(m/i)*m)/2;
if(i*i==m||i==1) continue;
if (ck(m/i)) ans+=(1ll*euler(i)*m)/2;
}
printf("Case #%d: %lld\n",cas,ans);
}
return 0;
}
//法2
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
#define int ll
const int N=1e4+10;
int n,m;
int a[N],p[N],vis[N],num[N];
int gcd(int x,int y){
return x%y?gcd(y,x%y):y;
}
signed main(){
int T;
scanf("%lld",&T);
for (int cas=1;cas<=T;cas++){
scanf("%lld%lld",&n,&m);
memset(vis,0,sizeof vis);
memset(num,0,sizeof num);
for (int i=1;i<=n;i++)scanf("%lld",&a[i]);
int cnt=0;
for (int i=1;i*i<=m;i++){
if (m%i==0){
p[++cnt]=i;
if (i*i!=m)p[++cnt]=m/i;
}
}
sort(p+1,p+1+cnt);
for (int i=1;i<=n;i++){
int d=gcd(a[i],m);
for (int j=1;j<=cnt;j++){
if (p[j]%d==0)vis[j]=1;
}
}
int ans=0;
for (int i=1;i<=cnt;i++){
if(vis[i]!=num[i]){
int t=(m-1)/p[i];
ans+=t*(t+1)/2*p[i]*(vis[i]-num[i]);
for (int j=i+1;j<=cnt;j++){
if(p[j]%p[i]==0){
num[j]+=vis[i]-num[i];
}
}
}
}
printf("Case #%lld: %lld\n",cas,ans);
}
return 0;
}
hdoj5201
hdoj5297
hdoj6021
hdoj5155
hdoj5471
hdoj2841
hdoj5794
hdoj6053
hdoj5468
hdoj4790
禁止类似码农教程的网站爬取,抄袭博客内容。
https://www.cnblogs.com/rair/

浙公网安备 33010602011771号