• topcoder srm 690 div1 -3


    1、给定一个数字$N$,从1到100的100个数字中选出$K$个数字(设为集合$S$),然后对$S$进行如下运算:

    (1)删除$S$中的某些数字;(可以删除0个数字)

    (2)将$S$中的某些数字取为它的相反数;(可以改变0个数字)

    (3)对$S$中的数字求和得到$ans$

    现在给出一种选择$K$个数的方法使得无论如何操作,$ans eq N$。$1leq N leq 100,1leq K leq 15$

    思路:从2开始枚举选择一个数字$x$,使得$N$%$x eq 0$,然后选择$x,2x,3x,...,Kx$。这样的话无论如何操作最后的$ans$都是$x$ 的倍数。但是当$N=60$时$x=7$,这是如果$K=15$,最后会选择105,这是可以特殊处理,把105换成1.因为7的任何倍数加减1都不会是60.

    #include <stdio.h>
    #include <string>
    #include <stack>
    #include <vector>
    #include <string.h>
    #include <algorithm>
    #include <assert.h>
    using namespace std;
    
    
    
    class WolfCardGame
    {
    public:
        vector<int> createAnswer(int n,int K)
        {
            vector<int> ans;
            for(int i=2;;++i) if(n%i)
            {
                for(int j=1;j<=K;++j) ans.push_back(i*j);
                if(i==7)
                {
                    ans[K-1]=1;
                }
                break;
            }
            return ans;
        }
    };
    

    2、对于一个有向树(树边是有方向的)$T$,定义$f(T)$表示这样的顶点对的个数:$(u,v)$,存在从$u$到$v$的路径。现在给定一棵$n$个顶点的无向树,给每条边选择一个方向,那么有$2^{n-1}$种方式,计算每种方式产生的有向树的$f$值之和。

    思路:考虑树分治。对于现在的树的重心$S$,那么对答案有贡献的顶点对有两种:要么顶点对其中的一个顶点是$S$,要么是跨过$S$的两个顶点。第一种容易计算,因为设另一个顶点是$u$,那么$u$与$S$之间的边的方向是相同的,而其他的边的方向任意,所以设它们之间的边的个数是$x$,那么对答案的贡献是$g(u)=2*2^{n-1-x}=2^{n-x}$。对于第二种,当前遍历的顶点$v$与之前遍历的顶点$u$之间的边方向是相同的,其余的边方向任意。所以设之前遍历的所有的$S$的子树得到的所有的节点的$g$值之和为$K$,$v$和$S$之间边的个数是$y$,那么当前节点的贡献为$h(v)=frac{K}{2^{y}}$.

    #include <stdio.h>
    #include <string>
    #include <stack>
    #include <vector>
    #include <string.h>
    #include <algorithm>
    #include <assert.h>
    using namespace std;
    
    
    const int N=100005;
    const int mod=1000000007;
    
    vector<int> g[N];
    int n;
    
    int a[N];
    int d[N];
    int fa[N];
    int p[N];
    
    
    int Pow(int a,int b)
    {
        int ans=1;
        while(b)
        {
            if(b&1) ans=(long long)ans*a%mod;
            a=(long long)a*a%mod;
            b>>=1;
        }
        return ans;
    }
    
    const int base=Pow(2,mod-2);
    
    void init()
    {
        p[0]=1;
        for(int i=1;i<N;++i) p[i]=(p[i-1]<<1)%mod;
    }
    
    int h[N];
    
    
    
    int aNum;
    int Son[N],MaxSon[N];
    
    
    void DFS(int u,int pre)
    {
        Son[u]=1;
        a[++aNum]=u;
        MaxSon[u]=0;
        for(int i=0;i<(int)g[u].size();++i)
        {
            int v=g[u][i];
            if(v!=pre&&!h[v])
            {
                DFS(v,u);
                Son[u]+=Son[v];
                if(Son[v]>MaxSon[u]) MaxSon[u]=Son[v];
            }
        }
    }
    
    int getcenter(int u)
    {
        aNum=0;
        DFS(u,-1);
        int ans=u,Min=aNum;
        for(int i=1;i<=aNum;++i)
        {
            int v=a[i];
            int tmp=max(aNum-MaxSon[v],MaxSon[v]);
            if(tmp<Min) Min=tmp,ans=v;
        }
        return ans;
    }
    
    
    int ans;
    
    void addAns(int x)
    {
        ans=(ans+x)%mod;
    }
    
    int CurrentSum;
    
    
    void calAns(int u,int pre,int preSum,int dep)
    {
        addAns(p[n-dep]);
        preSum=(long long)preSum*base%mod;
        addAns(preSum);
        CurrentSum=(CurrentSum+p[n-dep])%mod;
    
        for(int i=0;i<(int)g[u].size();++i)
        {
            int v=g[u][i];
            if(!h[v]&&v!=pre)
            {
                calAns(v,u,preSum,dep+1);
            }
        }
    }
    
    void dfs(int u)
    {
        u=getcenter(u);
    
        int preSum=0;
        for(int i=0;i<(int)g[u].size();++i)
        {
            int v=g[u][i];
            if(!h[v])
            {
                CurrentSum=0;
                calAns(v,u,preSum,1);
                preSum=(preSum+CurrentSum)%mod;
            }
        }
        h[u]=1;
        for(int i=0;i<(int)g[u].size();++i)
        {
            int v=g[u][i];
            if(!h[v]) dfs(v);
        }
    }
    
    
    
    class TreeWalker
    {
    public:
        int calc(int nn,int A0,int B,int C,int MOD)
        {
            n=nn;
            init();
            a[0]=A0;
            for(int i=1;i<n;++i) a[i]=((long long)a[i-1]*B+C)%MOD;
            for(int i=1;i<n;++i)
            {
                int u=a[i-1]%i;
                int v=i;
    
                g[u].push_back(v);
                g[v].push_back(u);
            }
            dfs(0);
            return ans;
        }
    };
    

      

  • 相关阅读:
    Redis杂谈
    General mistakes in parallel computing
    life of a NPTL pthread
    casting in C++
    function calling convention
    How exception works ?
    How `delete’ works ?
    How `new’ operator works ?
    老白的JAVA课程17 集合
    老白的JAVA课程16 卡片布局 javaBean
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/6907336.html
Copyright © 2020-2023  润新知