标签:
一种简单的表述法为:
另一种为:
例子:
一种表达是这样的:如果要把n个物件分配到m个容器中,必有至少一个容器容纳至少⌈n / m⌉个物件。(⌈x⌉大于等于x的最小的整数)
(1)两个集合容斥关系
(2)三个集合容斥关系
(3)n个集合的容斥关系
即1个集合的并-2个集合的并+3个集合的并-4个集合的并+5个集合的并......
题目意思是给n个数,选择其中一些数,使他们的和是n的k倍,k是自然数。只要输出其中正确的解就行
分析:
这n个数有n个前缀和,s[0],s[1],s[2]...s[n],并且对n取余
如果有s[i]==0,则输出0-i之间的数
如果不存在s[i]==0, 则s[i]一定在[1,n-1]之间 ,
根据鸽巢原理,n个物体放入n-1个盒子,至少有一个盒子有两个及以上的物体,所以题目一定有解
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxn 10010 int n; int arr[maxn],s[maxn],h[maxn]; int main() { while(~scanf("%d",&n)) { memset(h,-1,sizeof(h)); int x; for(int i=0;i<n;i++){ scanf("%d",&arr[i]); s[i]=(s[i-1]+arr[i])%n; } int a,b; for(int i=0;i<n;i++) { if(s[i]==0) { a=0; b=i; break; } else{ if(h[s[i]]!=-1) { a=h[s[i]]+1; b=i; break; } else h[s[i]]=i; } } printf("%d\n",b-a+1); for(int i=a;i<=b;i++)printf("%d\n",arr[i]); } return 0; }
和pku2365相同,c个孩子在n个neighbor中要选择糖果,使得糖果总和是c的倍数
注意鸽巢原理的使用范围,有n-1个盒子,至少n个物体,如果neighbor给的糖数为0,则盒子数量要减少,当然没有这种数据了
tip:数组下标尽量不要用-1,或者每次让s[-1]=0,进行初始化。这个地址由于没有跟着数组空间一起初始化,
所以其中的数据是不一定的,
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define maxn 100010 #define ll long long int c,n; int h[maxn],a[maxn],x; int main() { while(~scanf("%d%d",&c,&n)) { if(c==0&&n==0)break; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } memset(h,-1,sizeof(h)); int s=0; h[0]=0; for(int i=1;i<=n;i++) { s=(s+a[i])%c; // printf("* %d %d\n",i,s); if(h[s]!=-1) { for(int j=h[s]+1;j<i;j++) { printf("%d ",j); } printf("%d\n",i); break; } else h[s]=i; } } return 0; }
x=[a,b] , y=[c,d] 求gcd(x,y)=k 的组合数 ,a=1,c=1 ,(x,y),(y,x)是同一种组合
用容斥原理+二进制枚举。
先把b/=k ,d/=k
问题变成x=[1,b] y=[1,d] ,其中(x,y)互质的对数
枚举x,预处理x的质因子,假设w是x的质因子,1-d中w的倍数有d/w个
假设f(n)表示1-d中n个x的质因子乘积的倍数
容斥原理:不与x互质的个数=f(1)-f(2)+f(3)-f(4)...
注意:答案很大,用long long存
#include<iostream> #include<cstdio> #include<cstring> #include<vector> using namespace std; #define maxn 100010 #define ll long long vector<int>v[maxn]; bool is[maxn]; void prime() { for(int i=0;i<maxn;i++)v[i].clear(); memset(is,false,sizeof(is)); is[0]=is[1]=true; for(int i=2;i<maxn;i++) { for(int j=i;j<maxn;j+=i) { if(!is[i]) { v[j].push_back(i); if(j>i)is[j]=true; } } } } int work(int u,int s,int d)// d是范围1-d s是状态压缩 u是素因子表 { int cnt=0; int mul=1; for(int i=0;i<v[u].size();i++) { if((1<<i)&s){ mul*=v[u][i]; cnt++; } } int all=d/mul-(u-1)/mul;//u-d 内s选择状态因子的倍数的个数(d>u) if(cnt%2==0)all=-all; return all; } int main() { prime(); int T; scanf("%d",&T); for(int ca=1;ca<=T;ca++) { int a,b,c,d,k; ll ans; scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); if(k==0)ans=0; else{ ans=0; b/=k;d/=k; if(b>d)b^=d^=b^=d; for(int i=1;i<=b;i++) { ans+=d-i+1;//(x,y) 和(y,x)算一种 选择范围i-d int p=(1<<v[i].size());//p是素因子是否选取的所有状态 for(int j=1;j<p;j++) { ans-=work(i,j,d); } } } printf("Case %d: %lld\n",ca,ans); } return 0; } /* 2 1 1 1 5 1 1 5 1 1 1 */
给你n(n很小)个长方形,求这中间任意长方形的面积并。容斥
tip:结构体数组会初始化为0,结构体变量不会初始化为0
因为这个tle,还以为是算法错了
#include<iostream> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; int n,m; struct rec { int x1,y1,x2,y2; }a[30]; vector<int>v; int s[(1<<20)+10]; rec intersec(rec a, rec b) { rec c; if(a.x2<=b.x1||a.y2<=b.y1||a.x1>=b.x2||a.y1>=b.y2){ c.x1=c.x2=c.y1=c.y2=0;//注意没有交集要赋值0,否则tle,In_exclusion中停不下来! return c; } c.x1=max(a.x1,b.x1); c.y1=max(a.y1,b.y1); c.x2=min(a.x2,b.x2); c.y2=min(a.y2,b.y2); return c; } int Area(rec r) { if(r.x1>=r.x2||r.y1>=r.y2) return 0; return (r.y2-r.y1)*(r.x2-r.x1); } int In_exclusion(int k,rec r) { if(k>=v.size()||Area(r)==0) { return 0; } int ret=0; for(int i=k;i<v.size();i++) { rec tmp=intersec(a[v[i]],r); ret+=Area(tmp)-In_exclusion(i+1,tmp); } return ret; } int main() { rec tot; tot.x1=tot.y1=0; tot.x2=tot.y2=1000; int ca=1; while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0)break; printf("Case %d:\n",ca++); for(int i=1;i<=n;i++)scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2); memset(s,0,sizeof(s));//do not forget else get tle for(int i=1;i<=m;i++) { v.clear(); int R; int id; scanf("%d",&R); int add=0; while(R--) { scanf("%d",&id); v.push_back(id); add=add|(1<<(id-1)); } if(s[add]==0)s[add]=In_exclusion(0,tot); printf("Query %d: %d\n",i,s[add]); } puts(""); } return 0; } /* 3 2 0 0 2 3 1 1 4 5 0 2 3 4 2 1 2 3 1 2 3 */
标签:
原文地址:http://www.cnblogs.com/kylehz/p/4414333.html