zoukankan      html  css  js  c++  java
  • bzoj 3195: [Jxoi2012]奇怪的道路

    链接:3195: [Jxoi2012]奇怪的道路

    • 大意:给定(n)(m)(k),求出满足下列两个要求的图的个数,允许重边己环和不联通:
    • 每条边(1<=|u-v|<=K)且每个点连边偶数。$n,mleq 30 (,)kleq 8$
    • 有个朴素的(Dp)就是状压(k),设(f_{i,j,s})表示前(i)个点,(j)条边,最后(k)个点的奇偶性为(s)的方案数。
    • 然后枚举(i)和谁连边向(j+1)转移,每个(s)再向(i+1)转移。
    • 写完后发现这个做法有(bug),因为同一个状态因为(i)向外连边的顺序不同而被重复记数了。
    • 其实很好解决,(i)连向相同一个点的边就很像背包问题中的一件物品,每一件物品都是不限量的(只是最终要求了奇偶)。
    • 想一想,我们的完全背包统计方案时并没有多开一维,但绝对不会重复计数的。
    • 原因很简单,在做背包问题时,各个物品的选取存在严格顺序,不存在选了几个物品(a),又选了一点别的,再去选了几个物品(a)的情况。
    • 所以这里应当严格区分出各个物品,在每一个物品内部做完全背包。
    • 代码很短
    #include<bits/stdc++.h>
    #define R register int
    using namespace std;
    const int mod=1000000007;
    int n,m,k,now,lm,f[2][35][600];
    void add(R &x,R y){x=(x+y>=mod?x+y-mod:x+y);}
    int main(){
    	freopen("s.in","r",stdin);
    	cin>>n>>m>>k,lm=(1<<(k+1)),f[now][0][0]=1;
    	for(R i=1;i<=n;++i){
    		now^=1,memset(f[now],0,sizeof(f[now]));
    		for(R j=0;j<=m;++j)
    			for(R S=0;S<(1<<k);++S)
    				f[now][j][S<<1]=f[now^1][j][S];
    		for(R p=1;p<=min(i-1,k);++p)
    			for(R j=0;j<=m;++j)
    				for(R S=0;S<lm;++S)
    					add(f[now][j+1][S^1^(1<<p)],f[now][j][S]);
    	}
    	cout<<f[now][m][0];
        return 0;
    }
    
    
  • 相关阅读:
    客户机(单线程 和多线程都可以用 主要是看服务器是单线程的还是多线程的)
    获得URl信息
    获取地址
    定时器的使用以及日期的学习
    生产者和消费者
    线程join
    线程的协作
    文件的解压与压缩
    文件的分割与合并
    以各种方式读写文件
  • 原文地址:https://www.cnblogs.com/Tyher/p/9827063.html
Copyright © 2011-2022 走看看