0219考试总结

来源:互联网 发布:淘宝 心语星店 编辑:程序博客网 时间:2024/06/05 10:43

T1

【题目大意】

n个人,每个人都有一枚邮票和一些喜欢的邮票。每次可以把任意个人的邮票进行一次轮换,并且轮换后每个人必须拿着一枚喜欢的邮票,求最终能否让每个人都拿到一枚喜欢的邮票。

【吐槽】

这题出得神坑,直把人往tarjan上带。

正解如下:

其实那个交换方式只是吓唬人的。

对于每一种分配方案,我们都可以构造出一种交换方案达到这样的效果。

所以就是判断能不能给每个人分配一枚他喜欢的邮票。

二分图匹配,左边是人右边是邮票,每个人向喜欢的邮票连边,求是否存在完备匹配。

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>using namespace std;#define FILE "Book"#define MAXN 20010#define INF 1000000000#define up(i,j,n) for(int i=j;i<=n;++i)#define dn(i,j,n) for(int i=j;i>=n;--i)struct node{int y,next,v,rel;}e[MAXN*4];int n,m,S,T,len,Link[MAXN],q[MAXN],level[MAXN];void insert(int x,int y,int v){e[++len].next=Link[x];Link[x]=len;e[len].y=y;e[len].v=v;e[len].rel=len+1;e[++len].next=Link[y];Link[y]=len;e[len].y=x;e[len].v=0;e[len].rel=len-1;}bool bfs(){memset(level,-1,sizeof(level));int head=0,tail=1;  level[S]=0;  q[1]=S;while(++head<=tail){for(int i=Link[q[head]];i;i=e[i].next){if(e[i].v&&level[e[i].y]<0){q[++tail]=e[i].y;level[q[tail]]=level[q[head]]+1;}}}return level[T]>=0;}int MAXFLOW(int x,int flow){if(x==T) return flow;int d=0,maxflow=0;for(int i=Link[x];i&&maxflow<flow;i=e[i].next){if(level[x]+1==level[e[i].y]&&e[i].v){if(d=MAXFLOW(e[i].y,min(e[i].v,flow-maxflow))){e[i].v-=d;  e[e[i].rel].v+=d;  maxflow+=d;}}}if(!maxflow)  level[x]=-1;return maxflow;}void solve(){int d(0),ans(0);while(bfs()) while(d=MAXFLOW(S,INF)) ans+=d;puts(ans==n?"YES":"NO");}void pre(){len=0;memset(Link,0,sizeof(Link));}int main(){freopen(FILE".in","r",stdin);freopen(FILE".out","w",stdout);while(~scanf("%d%d",&n,&m)){pre();up(i,1,m) {int x,y;scanf("%d%d",&x,&y);insert(x,y+n,1);}S=0;T=n*2+1;up(i,1,n)  insert(S,i,1),insert(i+n,T,1);solve();}return 0;}


T2

蒟蒻并不会写,留个坑。。。



T3

【题目大意】

给出n个变量,m个方程,以及t个限制。

方程是一些变量的和等于一个数,限制是某个变量不超过多少。

变量只能是非负整数,求解的个数。

【题解】

组合数学+容斥原理

首先如果这题没有t的限制,那么就是JZYZOI1890的原题了。

用挡板法可知方程解的个数为c[k+n-1][k-1]

如果有限制的话,我们用容斥原理进行计算即可。

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>using namespace std;typedef long long ll;const ll mod=1000000007;#define FILE "Equation"#define MAXN 1000100#define up(i,j,n) for(ll i=j;i<=n;++i)#define dn(i,j,n) for(ll i=j;i>=n;--i)namespace INIT{char buf[1<<15],*fs,*ft;inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}inline ll read(){ll x=0,f=1;  char ch=getc();while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getc();}while(isdigit(ch))  {x=x*10+ch-'0';  ch=getc();}return x*f;}}using namespace INIT;ll n,m,t,sum[MAXN],id[MAXN],c[MAXN],d[MAXN],iv[MAXN],inv[MAXN],vis[MAXN],use[MAXN],delt[MAXN],frac[MAXN],UP[MAXN];ll get(ll a,ll b){return frac[a]*iv[b]%mod*iv[a-b]%mod;}ll fast(ll a,ll b){ll ans(1);for(;b;b>>=1,a=a*a%mod)if(b&1)ans=ans*a%mod;return ans;}void pre(){frac[0]=frac[1]=iv[0]=iv[1]=1;up(i,2,2000000)  frac[i]=frac[i-1]*i%mod,iv[i]=(iv[mod%i]*(-mod/i)%mod+mod)%mod;up(i,2,2000000)  iv[i]=iv[i]*iv[i-1]%mod;}int main(){freopen(FILE".in","r",stdin);freopen(FILE".out","w",stdout);n=read(); m=read(); pre();up(i,1,m){sum[i]=read();up(j,1,sum[i])  id[read()]=i;c[i]=read();}t=read();  ll lim=1<<t,pr=1;up(i,1,t)  d[i]=read(),UP[i]=read();up(i,1,m){ll temp=get(c[i]+sum[i]-1,sum[i]-1);pr=pr*temp%mod;inv[i]=fast(temp,mod-2);}ll ans=pr;up(i,1,lim-1){ll flag=1,top=0;up(j,1,t)if(i&(1<<(j-1))){flag=-flag;if(vis[id[d[j]]]!=i){vis[id[d[j]]]=i;delt[id[d[j]]]=0;use[++top]=id[d[j]];}delt[id[d[j]]]+=UP[j]+1;}ll temp(pr);up(j,1,top){temp=temp*inv[use[j]]%mod;temp=temp*get(c[use[j]]-delt[use[j]]+sum[use[j]]-1,sum[use[j]]-1)%mod;}ans+=temp*flag;  ans=(ans%mod+mod)%mod;}printf("%lld\n",ans);return 0;}







0 0