• bzoj3162 独钓寒江雪


    为了找一个合适的hash函数爆OJ23333.

    网上其他题解已经很详细了,我记录一个自己感觉有点妙的细节:我们需要用方案数求组合数,但是方案数是对mod=10^9+7取过模的,这样真的对吗?

    注意C(n,m)%mod=C(n%mod,m%mod)*C(n/mod,m/mod)%mod,而本题中的m都小于mod,所以C(n/mod,m/mod)一定是C(n/mod,0)=1,所以把方案数取个模不影响组合数的计算.

    如果取模的数字小一些,比如对2333取模,这样直接做可能就会WA了.

    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<map>
    using namespace std;
    typedef unsigned long long ll;
    map<ll,int> f[2];    
    const int mod=1000000007;
    const int maxn=500005;
    int inv[maxn];
    void init(){
      inv[0]=1;
      inv[1]=1;
      for(int i=2;i<maxn;++i)inv[i]=inv[mod%i]*1ll*(mod-mod/i)%mod;
      for(int i=1;i<maxn;++i)inv[i]=inv[i-1]*1ll*inv[i]%mod;
    }
    int C(int n,int m){
      int ans=1;
      for(int i=0;i<m;++i)ans=ans*1ll*(n-i)%mod;
      ans=ans*1ll*inv[m]%mod;
      return ans;
    }
    struct edge{
      int to,next;
    }lst[maxn<<1];int len=1,first[maxn];
    void addedge(int a,int b){
      lst[len].to=b;lst[len].next=first[a];first[a]=len++;
    }
    int n;
    int cnt=0,ct[3];
    int sz[maxn],g[maxn];
    void get_root(int x,int p){
      sz[x]=1;
      for(int pt=first[x];pt;pt=lst[pt].next){
        if(lst[pt].to==p)continue;
        get_root(lst[pt].to,x);
        sz[x]+=sz[lst[pt].to];
        if(sz[lst[pt].to]>g[x])g[x]=sz[lst[pt].to];
      }
      if(n-sz[x]>g[x])g[x]=n-sz[x];
      if(g[x]<=n/2)ct[cnt++]=x;
    }
    ll HA[maxn];
    vector<ll> tmp[maxn];
    void getHa(int x,int p){
      for(int pt=first[x];pt;pt=lst[pt].next){
        if(lst[pt].to==p)continue;
        else{
          getHa(lst[pt].to,x);
          tmp[x].push_back(HA[lst[pt].to]);
        }
      }
      HA[x]=19;
      if(tmp[x].empty())return;
      sort(tmp[x].begin(),tmp[x].end());
      for(vector<ll>::iterator pt=tmp[x].begin();pt!=tmp[x].end();++pt){
        HA[x]=((HA[x]*12312123123+(*pt))^(*pt))+(*pt)+2333;
      }
    }
    void dp(int x,int p){
      if(f[0][HA[x]])return;
      for(int pt=first[x];pt;pt=lst[pt].next){
        if(lst[pt].to==p)continue;
        dp(lst[pt].to,x);
      }
      int ans1=1,ans0=1;
      ll old=-1;int cnt=0;
      int sz=tmp[x].size();
      for(int i=0;i<sz;++i){
        cnt++;
        if(i==sz-1||tmp[x][i]!=tmp[x][i+1]){
          ans1=ans1*1ll*C((f[0][tmp[x][i]]+cnt-1)%mod,cnt)%mod;
          ans0=ans0*1ll*C((f[0][tmp[x][i]]+f[1][tmp[x][i]]+cnt-1)%mod,cnt)%mod;
          cnt=0;
        }
      }
      f[0][HA[x]]=ans0;f[1][HA[x]]=ans1;
    }
    int main(){
      init();
      scanf("%d",&n);
      for(int i=1,a,b;i<n;++i){
        scanf("%d%d",&a,&b);addedge(a,b);addedge(b,a);
      }
      get_root(1,0);
      if(cnt==2){
        getHa(ct[0],ct[1]);getHa(ct[1],ct[0]);
        dp(ct[0],ct[1]);dp(ct[1],ct[0]);
        int ans=(f[0][HA[ct[0]]]*1ll*f[1][HA[ct[1]]]%mod)%mod;
        if(HA[ct[0]]!=HA[ct[1]]){
          ans=(ans+f[1][HA[ct[0]]]*1ll*f[0][HA[ct[1]]]%mod)%mod;
          ans=(ans+f[0][HA[ct[0]]]*1ll*f[0][HA[ct[1]]]%mod)%mod;
        }else{
          ans=(ans+(f[0][HA[ct[0]]]*1ll*f[0][HA[ct[1]]]%mod+f[0][HA[ct[0]]]+mod)%mod*1ll*inv[2]%mod)%mod;
        }
        printf("%d
    ",ans);
      }else{
        getHa(ct[0],0);
        dp(ct[0],0);
        printf("%d
    ",(f[0][HA[ct[0]]]+f[1][HA[ct[0]]])%mod);
      }
      return 0;
    }
    
    
  • 相关阅读:
    原创js脚本实现百度网盘任意文件强制下载
    百度网盘大文件直接下载与下载提速的简单方法
    MVP架构的一个小例子
    PCQQ
    WPF
    百度网盘的限速破解
    何德何能?
    Maven多模块+SpringBoot 编译失败:程序包xxx不存在
    将Spring Boot项目部署到阿里云服务器上(二、安装MySQL服务器)
    将Spring Boot项目部署到阿里云服务器上(一、安装JDK)
  • 原文地址:https://www.cnblogs.com/liu-runda/p/6950673.html
Copyright © 2020-2023  润新知