• 997D Cycles in product


    传送门

    题目大意

    https://www.luogu.org/problemnew/show/CF997D

    分析

    我们发现两棵树互不相关

    于是我们可以分别求出两棵树的信息

    我们点分,人啊按后设f[i][x]为从根出发走i步到x中间不经过根的方案数,g[i][x]为可以经过根的方案数

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cctype>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<ctime>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    using namespace std;
    #define add(x,y) x=(x+y)%mod
    const int mod = 998244353;
    int c[80][80],m;
    struct tree {
        int n,ans[80],f[80][5000],g[80][5000];
        int root,sum,siz[5000],w[5000],a[5000],tot;
        bool vis[5000];
        vector<int>v[5000];
        inline void getrt(int x,int fa){
          siz[x]=1;
          w[x]=0;
          for(int i=0;i<v[x].size();i++)
            if(v[x][i]!=fa&&!vis[v[x][i]]){
              getrt(v[x][i],x);
              siz[x]+=siz[v[x][i]];
              w[x]=max(w[x],siz[v[x][i]]);
            }
          w[x]=max(w[x],sum-siz[x]);
          if(!root||w[x]<w[root])root=x;
        }
        inline void dfs(int x,int fa){
          a[++tot]=x;
          siz[x]=1;
          for(int i=0;i<v[x].size();i++)
            if(v[x][i]!=fa&&!vis[v[x][i]]){
              dfs(v[x][i],x);
              siz[x]+=siz[v[x][i]];
            }
        }
        inline void work(int x){
          tot=0;
          dfs(x,0);
          int i,j,k;
          memset(f,0,sizeof(f));
          memset(g,0,sizeof(g));
          f[0][x]=g[0][x]=1;
          for(i=1;i<=m;i++)
            for(j=1;j<=tot;j++){
              for(k=0;k<v[a[j]].size();k++){
                if(vis[v[a[j]][k]])continue;
                if(a[j]!=x)add(f[i][a[j]],f[i-1][v[a[j]][k]]);
                add(g[i][a[j]],g[i-1][v[a[j]][k]]);
              }
            }
          for(i=1;i<=tot;i++){
              if(a[i]==x){
                for(j=0;j<=m;j++)add(ans[j],g[j][a[i]]);
              }else {
                for(j=0;j<=m;j++)
                  for(k=0;k+j<=m;k++)
                    add(ans[k+j],(long long)f[j][a[i]]*g[k][a[i]]%mod);
              }
          }
          vis[x]=1;
          for(i=0;i<v[x].size();i++)
            if(!vis[v[x][i]]){
              root=0;
              sum=siz[v[x][i]];
              getrt(v[x][i],x);
              work(root);
            }
        }
        inline void solve(){
          sum=n;
          root=0;
          memset(vis,0,sizeof(vis));
          memset(ans,0,sizeof(ans));
          getrt(1,0);
          work(root);
        }
    };
    tree t1,t2;
    int main(){
        int i,j,k;
        scanf("%d%d%d",&t1.n,&t2.n,&m);
        c[0][0]=1;
        for(i=1;i<=m;i++)c[i][i]=c[i][0]=1;
        for(i=1;i<=m;i++)
          for(j=1;j<i;j++)c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
        for(i=0;i<=t1.n;i++)t1.v[i].clear();
        for(i=0;i<=t2.n;i++)t2.v[i].clear();
        for(i=1;i<t1.n;i++){
          int x,y;
          scanf("%d%d",&x,&y);
          t1.v[x].push_back(y);
          t1.v[y].push_back(x);
        }
        for(i=1;i<t2.n;i++){
          int x,y;
          scanf("%d%d",&x,&y);
          t2.v[x].push_back(y);
          t2.v[y].push_back(x);
        }
        t1.solve(),t2.solve();
        int Ans=0;
        for(i=0;i<=m;i++)
          Ans=(Ans+(long long)t1.ans[i]*t2.ans[m-i]%mod*c[m][i]%mod)%mod;
        cout<<Ans;
        return 0;
    }
  • 相关阅读:
    idea maven 经常主目录自动变回默认怎么办
    .net5 quartz
    sed命令
    ubuntu静态ip
    powershell基础
    restsharp 107.3 json自动转小写 自动驼峰 问题
    CQRS与事件溯源模式
    abp 切换默认项目为pgsql
    .net ASPNETCORE_ENVIRONMENT 根据环境切换不同的配置文件
    交换机端口三种模式Access,Hybrid,Trunk收发数据处理过程 yi
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/10406275.html
Copyright © 2020-2023  润新知