51nod 1806 wangyurzee的树(purfer,容斥原理)

来源:互联网 发布:java中final和static 编辑:程序博客网 时间:2024/05/20 17:07

又涨知识了,purfer序列计算生成树个数,purfer序列讲解:http://www.cnblogs.com/zhj5chengfeng/archive/2013/08/23/3278557.html
前几天看这个题,以为一定要满足m个限制条件,就直接套公式算起来了,错了。看题解,说是容斥原理,感觉很懵逼,满足m个条件直接算就行了,怎么容斥?今天再看才想起来,是满足1个,2个,3个…….m个条件,奇+偶-,容斥。。。。。。
可是想到和能写出来完全是两码事这里写图片描述
大神题解的提示:“注意这题还有个坑点就是可能给你的条件里有个同一个点不能有两个度数的要求,所以容斥的时候一定不能出现重复的同一个点

参考代码:http://blog.csdn.net/sdfzyhx/article/details/72764665

using System;using System.IO;namespace timeless{    class Program    {        private static int mod = (int)1e9 + 7;        private static int MAXN = 1000010;        private static long[] u = null, d = null, fac = null, inv = null;        private static bool[] vis = null;        static void Main(string[] args)        {            StreamReader sr = new StreamReader(Console.OpenStandardInput());            StreamWriter sw = new StreamWriter(Console.OpenStandardOutput());            long n, m;            long res = 0;            string[] str = sr.ReadLine().Split(' ');            n = long.Parse(str[0]);            m = long.Parse(str[1]);            u = new long[20];            d = new long[20];            vis = new bool[20];            fac = new long[MAXN];            inv = new long[MAXN];            for (int i = 0; i < m; ++i)            {                str = sr.ReadLine().Split(' ');                u[i] = long.Parse(str[0]);                d[i] = long.Parse(str[1]);            }            if (n == 1)            {                sw.WriteLine("1");                sw.Flush();                sw.Close();                sr.Close();                return;            }            fac[0] = inv[0] = 1;            for (long i = 1; i <= n; ++i)                fac[i] = (fac[i - 1] * i) % mod;            inv[n] = qpow(fac[n],mod-2);            for (long i = n - 1; i >= 1; --i)                inv[i] = (inv[i + 1] * (i + 1)) % mod;            int cnt = 0,num = 0;            long tem = 1;            bool flag = false; ;            for (int S = 0; S < (1<<(int)m); ++S)            {                cls(vis);                cnt = num = 0;                tem = fac[n-2];                flag = false;                for (int i = 0; i < m; ++i)                {                    if (((S >> i) & 1) == 1)                    {                        if (vis[u[i]])                        {                            flag = true;                            break;                        }                        else                            vis[u[i]] = true;                        cnt++;                        num += ((int)d[i] - 1);                        tem = tem * inv[d[i] - 1] % mod;                    }                }                if (flag || num > n - 2)                    continue;                tem = (tem * inv[n - 2 - num] % mod) * qpow(n - cnt, n - 2 - num) % mod;                if ((cnt & 1) == 1)                    res = (res - tem + mod) % mod;                else                    res = (res + tem) % mod;            }            sw.WriteLine(res);            sw.Flush();            sw.Close();            sr.Close();        }        private static long qpow(long a, long b)        {            long res = 1;            while (b != 0)            {                if ((b&1) == (long)1) res = res * a % mod;                a = a * a % mod;                b = b >> 1;            }            return res;        }        private static void cls(bool[] vis)        {            for (int i = 0; i < vis.Length; ++i)                vis[i] = false;        }    }}
原创粉丝点击