zoukankan      html  css  js  c++  java
  • Uoj308【UNR #2】UOJ拯救计划

    分析:比较难分析的一道题,先把式子写出来,ans=∑C(k,i)*f(i),f(i)是选i个颜色的方案数.这个模数有点奇怪,比较小而且是合数,说不定就会有某种规律,如果i >= 3,可以发现C(k,i)一定是被6整除的,那么我们只需要考虑i=2和i=1的情况,i=1的情况比较好处理,这种情况下,m只有等于0,答案为k^n,然后可以发现,这不仅仅是对i=1的情况的分析,所以我们要先特判m=0.

          那么i=2的情况要怎么处理呢?把每个连通块单独分析,如果一个连通块有一个合法方案,反过来又是一个合法方案,所以一个连通块要么没有贡献,要么就是2,我们只需要把有贡献的连通块的个数cnt求出来,答案就是C(k,2)*2^cnt.一旦有一个连通块没有合法方案,那么答案就直接为0了.

    二分图方案数要一个一个连通块考虑,求方案数如果不用dp先写出式子,然后分析.如果模数非常奇怪,找找看有没有什么规律.

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    int T,n,m,k,head[100010],nextt[400010],to[400010],tot = 1;
    int col[100010],ans;
    bool flag = false;
    
    void add(int x,int y)
    {
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    int qpow(int a,int b)
    {
        int res = 1;
        while (b)
        {
            if (b & 1)
            res = (res * a) % 6;
            b >>= 1;
            a = (a * a) % 6;
        }
        return res;
    }
    
    void dfs(int x,int c)
    {
        col[x] = c;
        for (int i = head[x];i;i = nextt[i])
        {
            int v = to[i];
            if (col[v])
            {
                if (col[v] == col[x])
                {
                    flag = 1;
                    break;
                }
            }
            else
            dfs(v,3 - c);
        }
    }
    
    int main()
    {
        scanf("%d",&T);
        while (T--)
        {
            memset(head,0,sizeof(head));
            memset(col,0,sizeof(col));
            ans = 1;
            tot = 1;
            flag = 0;
            scanf("%d%d%d",&n,&m,&k);
            if (m == 0)
            printf("%d
    ",qpow(k,n));
            else
            {
                for (int i = 1; i <= m; i++)
                {
                    int a,b;
                    scanf("%d%d",&a,&b);
                    add(a,b);
                    add(b,a);
                }
                for (int i = 1; i <= n; i++)
                {
                    if (!col[i])
                    {
                        dfs(i,1);
                        if (flag)
                        {
                            ans = 0;
                            break;
                        }
                        ans *= 2;
                        ans %= 6;
                    }
                }
                printf("%d
    ",((((k - 1) * k / 2)% 6) * ans) % 6);
            }
        }
    
    
        return 0;
    }
  • 相关阅读:
    [Apache commons系列]DBUtils 示例代码
    关于syslog
    Phoenix Tips (1)
    Phoenix 常用函数
    Phoenix 的数据类型
    最简单的Phoenix 访问 HBase例子
    SVNKIT 主要方法
    Linux 集群时钟同步
    Linux 集群时钟同步
    Linux 下定时提交SVN
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7511472.html
Copyright © 2011-2022 走看看