【JZOJ4816】label

来源:互联网 发布:茗记4知乎 编辑:程序博客网 时间:2024/05/17 14:15

Description

给出一棵树,给每个节点赋值一个[1,m]之间的权值,要求有边相连的两个点差绝对值k。求方案数,答案模109+7

Solution

20分:

Fi,j=vsonik=1mFv,k(|kj|k)

40分:
我们发现可取F是连续的,维护一个前缀和即可。

100分:
找规律发现,Fi的值是对称的,且中间一大段都是相同的,那么我们只要处理Fi的前面一些,中间直接乘起来即可。

Code

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<queue>#include<cmath>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)#define N 101#define M 201#define MAX 10200#define mo 1000000007#define ll long longusing namespace std;int to[M],next[M],last[M],num=0;int K;int fa[N];void link(int x,int y){    num++;    to[num]=y;    next[num]=last[x];    last[x]=num;}int n,m;ll f[N][MAX],g[N][MAX],z[N][MAX];int p[N];int zz;ll sum(int x,int y){    if(y<=p[x]) return g[x][y];    else if(y<=m-p[x]+1) return (g[x][p[x]]+f[x][p[x]+1]*(y-p[x])%mo)%mo;    else return (g[x][p[x]]+f[x][p[x]+1]*(m-2*p[x])%mo+z[x][y-m+p[x]])%mo;}void dfs(int x){    fo(i,1,zz) f[x][i]=1;    for(int i=last[x];i;i=next[i])    {        int v=to[i];        if(fa[x]!=v)        {            fa[v]=x;            dfs(v);            fo(j,1,zz)            {                ll tmp=0;                tmp=(tmp+sum(v,max(j-K,0)))%mo;                tmp=(tmp+sum(v,m)-sum(v,min(j+K,m+1)-1)+mo)%mo;                if(!K) tmp=(tmp-f[v][j]+mo)%mo;                f[x][j]=f[x][j]*tmp%mo;            }        }    }    fo(i,1,zz)    if(f[x][i]==f[x][i+1]) {p[x]=i;break;}    if(!p[x]) p[x]=zz;    fo(i,1,zz)    {        g[x][i]=(g[x][i-1]+f[x][i])%mo;        z[x][i]=(z[x][i-1]+f[x][p[x]-i+1])%mo;    }}int main(){    freopen("label.in","r",stdin);    freopen("label.out","w",stdout);    int T;    cin>>T;    while(T--)    {        num=0;        memset(last,0,sizeof(last));        memset(p,0,sizeof(p));        scanf("%d %d %d",&n,&m,&K);        fo(i,1,n-1)        {            int x,y;            scanf("%d %d",&x,&y);            link(x,y);            link(y,x);        }        zz=min(m,max((n-1)*K,2));        dfs(1);        printf("%lld\n",sum(1,m));    }}
1 0
原创粉丝点击