• [loj2462]完美的集合


    当$k$个集合依次为$S_{1},S_{2},...,S_{k}$时,称$x$合法当且仅当:

    1.$forall 1le ile k,xin S_{i}$

    2.$forall yin igcup_{i=1}^{k}S_{i}$,$dis(x,y) imes v_{y}le Max$

    注意到这些合法的$x$必然构成一个连通块,证明如下:

    考虑两个合法点$x$和$y$以及$x$到$y$这条路径上一个点$z$($z e x,y$),由于$S_{i}$要求连通,因此$zin S_{i}$,同时对于任意点$t$,$dis(z,t) imes v_{t}<max(dis(x,t),dis(y,t)) imes v_{t}le Max$,因此也满足第2个条件

    此时,我们就可以利用点数-边数=1的性质,具体来说:

    对于所有$x$,求出令$x$合法的方案数;对于所有$(x,y)$,求出令$(x,y)$合法的方案数(称一条边$(x,y)in E$合法当且仅当$x$合法且$y$合法)

    将两者相减,考虑使得合法集合非空的方案,该合法集合中每一个点都贡献了1个收益,每一条边都贡献了一个-1的收益,因此一共恰好被计算点数-边数=1次

    令$x$合法的方案数,可以通过dp求,具体来说,由于强制包含$x$,以$x$为根建树后在dfs序上dp,状态中关于价值的一维强制最大,即再记录另一个dp数组表示最大价值即可

    (特别的,要对无$dis(x,y) imes v_{y}$的限制再做一次,因为对于“完美的集合”没有这个限制,若这样的最大值更大则答案必然为0)

    接下来,我们相当于要计算一个组合数,可以转换为阶乘的形式,即求$n!equiv ans(mod 5^{23})$(题中所给的大模数即为$5^{23}$,另外注意乘法需要转换为加法,可以以500为进制)

    $o(log_{5}n)$统计出其中5的次数,用$5^{t}v$的形式来表示(其中$5 otmid v$)答案,之后记$g_{n}=prod_{1le ile n,5 otmid i}i$,即有$v=prod_{ige 0}g_{lfloorfrac{n}{5^{i}} floor}$,接下来即考虑如何求$g_{n}$(这个$n$代指$lfloorfrac{n}{5^{i}} floor$)

    记$n'=lfloorfrac{n}{5} floor$,则有$g_{n}=g_{5n'}prod_{i=5n'+1}^{n}i$,后者暴力计算即可,之后即求$g_{5n'}$

    构造函数$f_{n}(x)=prod_{1le ile 5n,5 otmid i}(x+i)$(用多项式的形式存储),初始$f_{0}(x)=1$,即求$g_{5n'}=f_{n'}(x)[x^{0}]$(指常数项系数)

    考虑$f_{2n}(x)=f_{n}(x)f_{n}(x+5n)$和$f_{n+1}=f_{n}(x)prod_{i=1}^{4}(x+5n+i)$,由此即可推出$f_{n'}(x)$,但如果暴力计算,复杂度为$o(n^{2}log_{2}n)$

    事实上,对于$f_{n}(x)[x^{i}]$,我们只关心于其对$5^{23-i}$取模的结果,那么对$ige 23$时即对1取模,显然不需要计算,因此仅保留前23项(具体实现都对$5^{23}$取模即可),复杂度降为$o(23^{2}log_{2}n)$

    由于乘法还需要一个log,以及要计算$o(log_{5}n)$个$g_{n}$,总复杂度为$o(n^{2}m+23^{2}nlog^{3}mod)$,可以通过

    关于$f_{n}(x)[x^{i}]$对$5^{23-i}$取模的证明:

    归纳这样的正确性,称$f(x)=f'(x)$当且仅当$f(x)[x^{i}]equiv f'(x)[x^{i}](mod 5^{23-i})$

    接下来即求证若$f_{n}(x)=f'_{n}(x)$,$f_{2n}(x)=f'_{2n}(x)$且$f_{n+1}(x)=f'_{n+1}(x)$

    先考虑对于$f(x)=f'(x)$且$g(x)=g'(x)$,不难推得$f(x)g(x)=f'(x)g'(x)$,那么对于$f_{n+1}(x)=f'_{n+1}(x)$正确性显然

    同时对于$f_{2n}(x)=f'_{2n}(x)$,也就是要证明$f_{n}(x+5n)=f'_{n}(x+5n)$,代入后也可以证明

    根据上面的这个性质,不难得到最终$f_{n}(x)=f'_{n}(x)$,即$f'_{n'}[x^{0}]equiv f_{n'}[x^{0}](mod 5^{23})$

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 105
      4 #define M 10005
      5 #define ll long long
      6 #define pll pair<ll,ll>
      7 #define fi first
      8 #define se second
      9 struct ji{
     10     int nex,to,len;
     11 }edge[N<<1];
     12 pll g[M],f[N][M];
     13 int E,n,m,k,x,y,z,head[N],w[N],v[N],dfn[N],sz[N],dep[N];
     14 ll lim,mod,mx,ans;
     15 void add(int x,int y,int z){
     16     edge[E].nex=head[x];
     17     edge[E].to=y;
     18     edge[E].len=z;
     19     head[x]=E++;
     20 }
     21 void dfs(int k,int fa,int s){
     22     dfn[++dfn[0]]=k;
     23     sz[k]=1;
     24     dep[k]=s;
     25     for(int i=head[k];i!=-1;i=edge[i].nex)
     26         if (edge[i].to!=fa){
     27             dfs(edge[i].to,k,s+edge[i].len);
     28             sz[k]+=sz[edge[i].to];
     29         }
     30 }
     31 ll mul(ll x,ll y){
     32     ll s=x,ans=0;
     33     while (y){
     34         ans=(ans+y%500*s)%mod;
     35         s=500*s%mod;
     36         y/=500;
     37     }
     38     return ans;
     39 }
     40 void exgcd(ll a,ll b,ll &x,ll &y){
     41     if (!b){
     42         x=1,y=0;
     43         return;
     44     }
     45     exgcd(b,a%b,y,x);
     46     y-=(a/b)*x;
     47 }
     48 struct num{
     49     ll t,v;
     50     num operator * (const num &k)const{
     51         return num{t+k.t,mul(v,k.v)};
     52     }
     53     num inv(){
     54         ll x,y;
     55         exgcd(v,mod,x,y);
     56         if (x>=0)x%=mod;
     57         else x+=(-x+mod-1)/mod*mod;
     58         return num{-t,x};
     59     }
     60 }o;
     61 struct poly{
     62     ll a[23];
     63     poly(int k){
     64         memset(a,0,sizeof(a));
     65         a[0]=k;
     66     }
     67     poly operator + (const poly &k)const{
     68         poly ans=poly(0);
     69         for(int i=0;i<23;i++)ans.a[i]=(a[i]+k.a[i])%mod;
     70         return ans;
     71     }
     72     poly operator * (const poly &k)const{
     73         poly ans=poly(0);
     74         for(int i=0;i<23;i++)
     75             for(int j=0;j<23;j++)
     76                 if (i+j<23)ans.a[i+j]=(ans.a[i+j]+mul(a[i],k.a[j]))%mod;
     77         return ans;
     78     }
     79 };
     80 poly dfs(ll n){
     81     poly ans=poly(1);
     82     if (!n)return ans;
     83     ans=dfs(n>>1);
     84     poly s=poly(1),ss=poly(0);
     85     for(int i=0;i<23;i++){
     86         for(int j=0;j<=i;j++)ss.a[j]=(ss.a[j]+mul(s.a[j],ans.a[i]))%mod;
     87         for(int j=min(i+1,22);j;j--)s.a[j]=(mul(s.a[j],5*(n/2))+s.a[j-1])%mod;
     88         s.a[0]=mul(s.a[0],5*(n/2));
     89     }
     90     ans=ans*ss;
     91     if (n&1)
     92         for(int i=1;i<5;i++){
     93             for(int j=22;j;j--)ans.a[j]=(mul(ans.a[j],5*(n-1)+i)+ans.a[j-1])%mod;
     94             ans.a[0]=mul(ans.a[0],5*(n-1)+i);
     95         }
     96     return ans;
     97 }
     98 ll fac_5(ll n){
     99     ll nn=n/5,ans=1;
    100     for(ll i=nn*5+1;i<=n;i++)ans=mul(ans,i);
    101     return mul(ans,dfs(nn).a[0]);
    102 }
    103 num fac(ll n){
    104     num ans=num{0,fac_5(n)};
    105     for(ll i=5;i<=n;i*=5){
    106         ans.t+=n/i;
    107         ans.v=mul(ans.v,fac_5(n/i));
    108     }
    109     return ans;
    110 }
    111 ll c(ll n,ll m){
    112     if (n<m)return 0;
    113     num ans=fac(n)*o*fac(n-m).inv();
    114     if (ans.t>=23)return 0;
    115     for(int i=0;i<ans.t;i++)ans.v=ans.v*5%mod;
    116     return ans.v;
    117 }
    118 pll merge(pll x,pll y){
    119     if (x.fi<y.fi){
    120         x.fi=y.fi;
    121         x.se=0;
    122     }
    123     if (x.fi==y.fi)x.se=(x.se+y.se)%mod;
    124     return x;
    125 }
    126 void calc(int p){
    127     f[dfn[0]+1][0]=make_pair(0,1);
    128     for(int i=1;i<=m;i++)f[dfn[0]+1][i]=make_pair(-1,0);
    129     for(int i=dfn[0];i;i--){
    130         int x=dfn[i];
    131         for(int j=0;j<=m;j++)f[i][j]=f[i+sz[x]][j];
    132         if ((p)&&(1LL*dep[x]*v[x]>lim))continue;
    133         for(int j=m;j>=w[x];j--){
    134             pll o=f[i+1][j-w[x]];
    135             o.fi+=v[x];
    136             f[i][j]=merge(f[i][j],o);
    137         }
    138     }
    139 }
    140 int main(){
    141     mod=1;
    142     for(int i=0;i<23;i++)mod*=5;
    143     scanf("%d%d%d%lld",&n,&m,&k,&lim);
    144     o=fac(k).inv();
    145     for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    146     for(int i=1;i<=n;i++)scanf("%d",&v[i]);
    147     memset(head,-1,sizeof(head));
    148     for(int i=1;i<n;i++){
    149         scanf("%d%d%d",&x,&y,&z);
    150         add(x,y,z);
    151         add(y,x,z);
    152     }
    153     for(int i=1;i<=n;i++){
    154         dfn[0]=0;
    155         dfs(i,0,0);
    156         calc(0);
    157         for(int j=0;j<=m;j++)mx=max(mx,f[1][j].fi);
    158     }
    159     for(int i=1;i<=n;i++){
    160         dfn[0]=0;
    161         dfs(i,0,0);
    162         calc(1);
    163         ll sum=0;
    164         for(int j=0;j<=m;j++)
    165             if (f[1][j].fi==mx)sum=(sum+f[1][j].se)%mod;
    166         ans=(ans+c(sum,k))%mod;
    167     }
    168     for(int i=0;i<E;i+=2){
    169         int x=edge[i].to,y=edge[i^1].to;
    170         dfn[0]=0;
    171         dfs(x,y,edge[i].len);
    172         calc(1);
    173         g[0]=make_pair(-1,0);
    174         for(int j=1;j<=m;j++)g[j]=merge(g[j-1],f[1][j]);
    175         dfn[0]=0;
    176         dfs(y,x,edge[i].len);
    177         calc(1);
    178         ll sum=0;
    179         for(int j=w[x];j<=m-w[y];j++)
    180             if (g[j].fi+f[1][m-j].fi==mx)sum=(sum+mul(g[j].se,f[1][m-j].se))%mod;
    181         ans=(ans+mod-c(sum,k))%mod;
    182     }
    183     printf("%lld",ans);
    184 }
    View Code
  • 相关阅读:
    第二周进度条博客
    软件工程个人作业01
    动手动脑1
    构建之法阅读笔记06
    构建之法阅读笔记05
    构建之法阅读笔记04
    poj 1631 LIS
    poj 1609 dp
    lightoj 1198 最大权重匹配
    hdu4696 想法题
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14324954.html
Copyright © 2020-2023  润新知