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;
    }
};

  

原文地址:https://www.cnblogs.com/jianglangcaijin/p/6907336.html