zoukankan      html  css  js  c++  java
  • 省选模拟赛 让苍天知道我不认输(40分)

    分析:强大的bitset......

       对于每一个点i,其bitset f[i][j]表示f(t(i -> j)). 枚举两个点i,j. 如果f[i][j] = 1. 那么f[i] & f[j]中1的个数就是i,j的贡献. 否则f[i]和f[j]相同位置处0的个数就是贡献. 先以每个点为起点dfs一次就能预处理出f了.

       用bitset主要是因为想确定i,j连到的是不是同一个点. 直接求方案数可能不合法.

    #include <cstdio>
    #include <bitset>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 1010;
    int n,y,k,r,a[maxn],head[maxn],to[maxn * 2],nextt[maxn * 2],tot = 1,vis[maxn];
    bitset <maxn> f[maxn],b,temp1,temp2,temp;
    long long ans;
    
    void add(int x,int y)
    {
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    void dfs(int S,int u,int z,int ki)
    {
        int temp = (z + a[u] * ki % y) % y;
        if (temp == r)
            f[S][u] = 1;
        else
            f[S][u] = 0;
        vis[u] = 1;
        for (int i = head[u];i;i = nextt[i])
        {
            int v = to[i];
            if (!vis[v])
            {
                int tmp = ki * k % y;
                dfs(S,v,temp,tmp);
            }
        }
    }
    
    int main()
    {
        scanf("%d%d%d%d",&n,&y,&k,&r);
        for (int i = 1; i <= n; i++)
            scanf("%d",&a[i]);
        for (int i = 1; i < n; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        for (int i = 1; i <= n; i++)
        {
            memset(vis,0,sizeof(vis));
            dfs(i,i,0,1);
        }
        for (int i = 1; i <= n; i++)
            b[i] = 1;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                if (f[i][j] == 1)
                {
                    temp = f[i] & f[j];
                    ans += temp.count();
                }
                else
                {
                    temp1 = f[i] ^ b;
                    temp2 = f[j] ^ b;
                    temp = temp1 & temp2;
                    ans += temp.count();
                }
            }
        }
        printf("%lld
    ",ans);
    
        return 0;
    }
  • 相关阅读:
    Oracle9使用oradata恢复数据库
    我该怎么安排下属的工作项目经理如何分配任务
    如果说中国的程序员技术偏低,原因可能在这里
    项目经理问:为什么总是只有我在加班 – 挂包袱现象
    【转】面试真经
    [JAVA]PING和TELNET用法介绍
    Hello World 你懂的
    线程间操作控件
    获取客户端相关信息
    winfrom 特效 [转载]
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8717134.html
Copyright © 2011-2022 走看看