「训练日志14 」(8.9) 失败

还说啥啊,这就是不行啊。

T1 建设城市

  数学题,组合排列,我连一点思路都没有。

  真的不会。

  容斥,这是能想到的,但完全不会容斥啊。

  先挂上一篇DeepInC博客,写的很好。

  我们先考虑总体不合法的地方至少有0个的情况,情况是$C_{m-1}^{n-1}$,裸的挡板法,问题其实就是在$n$个里面插入$m-n$个数,可以为空的方案数,可以表示 为$C_{n+(m-n)-1}^{m-n}$,可以化简,不再缀述。

  然后再去看DeepInC博客就好了,我只简单的给自己提醒一下。

  公式$C_n^i * C_{m-i*k-1}^{n-1}$

  然后为什么要减去$i*k$呢,意思是把分给$i$个$k$个元素,让他们到达最大值,然后开始分剩下的元素,一定能使这$i$个超限,这也做到了“至少”,然后就挡板法解决了。

  小弟不才。

 1 #include<cstdio>
 2 #include<iostream>
 3 #define LL long long
 4 #define HZOI std
 5 using namespace HZOI;
 6 const int mod=998244353;
 7 const int N=1e7+3;
 8 int n,m,k,p;
 9 LL Finv[N],inv[N],F[N];
10 LL ans,ooo;
11 inline void Init();
12 inline LL Comb(int ,int );
13 int main()
14 {
15 //    freopen("1.out","w",stdout);
16     scanf("%d%d%d",&n,&m,&k);
17     Init();
18     if (n>m) {puts("0");return 0;}
19     ooo=1;
20     for (int i=0; i<=n and m-i*k-1>=0; ++i,ooo=-ooo)
21         ans=(ans+ooo*Comb(n,i)*Comb(m-i*k-1,n-1)%mod+mod)%mod;
22     printf("%lld
",(ans+mod)%mod);
23 }
24 inline LL Comb(int x,int y)
25 {
26     if (y>x) return 0;
27     return F[x]*1ll*Finv[y]%mod*Finv[x-y]%mod;
28 }
29 inline void Init()
30 {
31     inv[1]=1;
32     for (int i=2; i<=m; ++i)
33         inv[i]=(mod-mod/i)*1ll%mod*inv[mod%i]%mod;
34     Finv[0]=F[0]=1;
35     for (int i=1; i<=m; ++i)
36         F[i]=F[i-1]%mod*i%mod,
37         Finv[i]=Finv[i-1]%mod*inv[i]%mod;
38 }
建设城市

T2 轰炸行动

  一道裸的语文题。

  乍一看题,看不懂,那种不知道要干嘛的看不懂,样例不会玩,$Dfs$不会打,心情十分激动。

  然后,就按着错的思路想了半天。

  很难受。

  实际上一个点,它所能到达的那一条链上的点都不能同时炸。然后呢,发现一个很显然的性质:一个环,需要炸的次数就是它的大小。然后这道题就没了。

  考试的时候就知道一个缩点。缩点之后要干啥?不知道,就会瞎缩,然后就懵了。

  然后一个拓扑,从入度为0的点开始搜,搜到最后找到最长链,$ok$了。

  小弟不才。

  

  1 #include<cstdio>
  2 #include<cstring>
  3 #define HZOI std
  4 using namespace HZOI;
  5 const int N=1e7+3;
  6 int n,m,ans;
  7 int tt,first[N],vv[N<<1],nx[N<<1];
  8 int TT,First[N],VV[N<<1],Next[N<<1];
  9 int num,tot,stc[N<<1],dfn[N],low[N],be[N],sz[N];
 10 int head,tail,q[N],du[N],vis[N],dep[N];
 11 inline void Add(int ,int );
 12 inline void NewAdd(int ,int );
 13 void Tarjan(int );
 14 inline void Solve();
 15 inline int read();
 16 inline int min(int a,int b) {return a<b?a:b;}
 17 inline int max(int a,int b) {return a>b?a:b;}
 18 int main()
 19 {
 20     n=read(),m=read();
 21     for (int i=1,x,y; i<=m; ++i)
 22     {
 23         x=read(),y=read();
 24         Add(x,y);
 25     }
 26     for (int i=1; i<=n; ++i)
 27         if (!dfn[i])
 28             Tarjan(i);
 29     for (int i=1; i<=n; ++i)
 30         for (int j=first[i]; j; j=nx[j])
 31         {
 32             if (be[i]==be[vv[j]]) continue;
 33             NewAdd(be[i],be[vv[j]]),++du[be[vv[j]]];
 34         }
 35     memset(vis,0,sizeof(vis));
 36     Solve();
 37     printf("%d
",ans);
 38 }
 39 inline void Solve()
 40 {
 41     head=tail=0;
 42     for (int i=1; i<=num; ++i)
 43         if (!du[i])
 44             q[++tail]=i,vis[i]=1,dep[i]=sz[i];
 45     while (head^tail)
 46     {
 47         int x=q[++head];
 48         for (int i=First[x]; i; i=Next[i])
 49         {
 50             int ver=VV[i];
 51             if (vis[ver]) continue;
 52             dep[ver]=max(dep[ver],dep[x]+sz[ver]);
 53             if (!(--du[ver])) q[++tail]=ver,vis[ver]=1;
 54         }
 55         ans=max(ans,dep[x]);
 56     }
 57 }
 58 void Tarjan(int k)
 59 {
 60     dfn[k]=low[k]=++tot;
 61     vis[k]=1;
 62     stc[++tail]=k;
 63     for (int i=first[k]; i; i=nx[i])
 64     {
 65         int ver=vv[i];
 66         if (!dfn[ver])
 67         {
 68             Tarjan(ver);
 69             low[k]=min(low[k],low[ver]);
 70         }
 71         if (vis[ver]) low[k]=min(dfn[ver],low[k]);
 72     }
 73     if (dfn[k]==low[k])
 74     {
 75         int to;
 76         ++num;
 77         do 
 78         {
 79             to=stc[tail--];
 80             be[to]=num;
 81             vis[to]=0;
 82             ++sz[num];
 83         }while (to^k);
 84     }
 85 }
 86 inline void NewAdd(int u,int v)
 87 {
 88     VV[++TT]=v,Next[TT]=First[u],First[u]=TT;
 89 }
 90 inline void Add(int u,int v)
 91 {
 92     vv[++tt]=v,nx[tt]=first[u],first[u]=tt;
 93 }
 94 inline int read()
 95 {
 96     int nn=0;char ch=getchar();
 97     while (ch<'0' or ch>'9') ch=getchar();
 98     while (ch>='0' and ch<='9') nn=(nn<<3)+(nn<<1)+(ch^48),ch=getchar();
 99     return nn;
100 }
轰炸行动
原文地址:https://www.cnblogs.com/LH-Xuanluo/p/11330374.html