• bzoj 5498: [2019省队联测]皮配【dp】


    是个神仙dp……
    参考:https://www.luogu.org/blog/xzz-233/solution-p5289
    设f[i][j][k]是前i个有限制的城市,所有学校中选蓝色阵营有j人,有限制的学校中鸭派系有k人的方案数;g[i][j]是前i个没有限制的城市,蓝色阵营有j人的方案数;h[i][j]是前i个没有限制的学校,鸭派系有j人的方案数
    f的转移枚举当前阵营
    全dp出来之后,把gh前缀和处理,然后一段一段的和f合并加到ans上

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int N=2505,mod=998244353;
    int T,n,c,c0,c1,d0,d1,k,m,ss,ans,b[N],s[N],f[N][N],f1[N][N],f2[N][N],g[N],h[N],ki[N],kp[N],v[N],ct[N],sum[N],sm[N];
    vector<int>sc[N];
    void jia(int &x,int y)
    {
    	if((x+=y)>=mod)
    		x-=mod;
    }
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    int main()
    {
    	T=read();
    	while(T--)
    	{
    		memset(f,0,sizeof(f));
    		memset(f1,0,sizeof(f1));
    		memset(f2,0,sizeof(f2));
    		memset(g,0,sizeof(g));
    		memset(h,0,sizeof(h));
    		memset(sm,0,sizeof(sm));
    		memset(sum,0,sizeof(sum));
    		memset(ct,0,sizeof(ct));
    		for(int i=0;i<N;i++)
    			sc[i].clear();
    		ss=0,ans=0;
    		n=read(),c=read(),c0=read(),c1=read(),d0=read(),d1=read();
    		for(int i=1;i<=n;i++)
    			b[i]=read(),s[i]=read(),sum[b[i]]+=s[i],ss+=s[i];
    		m=k=read();
    		for(int i=1;i<=n;i++)
    			v[i]=-1;
    		for(int i=1;i<=k;i++)
    		{
    			ki[i]=read(),kp[i]=read();
    			ct[i]=b[ki[i]];
    			sc[b[ki[i]]].push_back(ki[i]);
    			v[ki[i]]=kp[i];
    		}
    		sort(ct+1,ct+1+m);
    		m=unique(ct+1,ct+1+m)-ct-1;
    		for(int i=1;i<=n;i++)
    			if(v[i]!=-1)
    				sm[b[i]]+=s[i];
    		f[0][0]=1;
    		for(int i=1,s1=0,s2=0;i<=m;i++)
    		{
    			s1=min(c0,s1+sum[ct[i]]),s2=min(d0,s2+sm[ct[i]]);
    			for(int o=0;o<=1;o++)
    			{
    				for(int j=0;j<=s1;j++)
    					for(int k=0;k<=s2;k++)
    						f1[j][k]=f[j][k];
    				for(int l=0,len=sc[ct[i]].size();l<len;l++)
    				{
    					int x=sc[ct[i]][l];
    					for(int j=s1;j>=0;j--)
    						for(int k=s2;k>=0;k--)
    						{
    							if(o==0)
    							{
    								f1[j][k]=0;
    								if(v[x]!=1&&j>=s[x])
    									jia(f1[j][k],f1[j-s[x]][k]);
    								if(v[x]!=0&&j>=s[x]&&k>=s[x])
    									jia(f1[j][k],f1[j-s[x]][k-s[x]]);
    							}
    							else
    							{
    								if(v[x]==3)
    									f1[j][k]=0;
    								if(v[x]!=2&&k>=s[x])
    									jia(f1[j][k],f1[j][k-s[x]]);
    							}
    						}
    				}
    				if(o==0)
    				{
    					int nw=sum[ct[i]]-sm[ct[i]];
    					for(int j=s1;j>=0;j--)
    						for(int k=s2;k>=0;k--)
    						{
    							if(j>=nw)
    								f1[j][k]=f1[j-nw][k];
    							else
    								f1[j][k]=0;
    						}
    					for(int j=0;j<=s1;j++)
    						for(int k=0;k<=s2;k++)
    							f2[j][k]=f1[j][k];
    				}
    				else
    				{
    					for(int j=0;j<=s1;j++)
    						for(int k=0;k<=s2;k++)
    							f[j][k]=(f1[j][k]+f2[j][k])%mod;
    				}
    			}
    		}
    		g[0]=1;
    		for(int i=1,smm=0;i<=c;i++)
    			if(sc[i].empty()&&sum[i])
    			{
    				smm=min(c0,smm+sum[i]);
    				for(int j=smm;j>=0;j--)
    					if(j>=sum[i])
    						jia(g[j],g[j-sum[i]]);
    			}
    		h[0]=1;
    		for(int i=1,smm=0;i<=n;i++)
    			if(v[i]==-1)
    			{
    				smm=min(d0,smm+s[i]);
    				for(int j=smm;j>=0;j--)
    					if(j>=s[i])
    						jia(h[j],h[j-s[i]]);
    			}
    		for(int i=1;i<=c0;i++)
    			jia(g[i],g[i-1]);
    		for(int i=1;i<=d0;i++)
    			jia(h[i],h[i-1]);
    		for(int i=0;i<=c0;i++)
    			if(ss-i-c1-1<c0-i)
    				for(int j=0;j<=d0;j++)
    					if(ss-j-d1-1<d0-j)
    						jia(ans,1ll*f[i][j]*(g[c0-i]-(ss-i-c1-1>=0?g[ss-i-c1-1]:0)+mod)%mod*(h[d0-j]-(ss-j-d1-1>=0?h[ss-j-d1-1]:0)+mod)%mod);
    		printf("%d
    ",(ans+mod)%mod);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Linux 信号signal处理机制
    va_start、va_arg、va_end、va_copy 可变参函数
    辛星笔记——VIM学习篇(推荐阅读)
    每个程序员都应该读的书
    igmpproxy源代码学习——配置信息加载 loadConfig
    windows下gvim搭建IDE
    插入排序与循环不变式
    6个变态的C语言程序
    安卓原生百度地图(5)导航和语音播报
    安卓原生百度地图(4)路线规划
  • 原文地址:https://www.cnblogs.com/lokiii/p/10712364.html
Copyright © 2020-2023  润新知